From 3a9ffef074afcbe24f5255a7c8c86f98cff341db Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 7 Jun 2023 13:17:09 +0200 Subject: [PATCH] NRF --- core/.gitignore | 2 + core/Makefile | 43 +- core/SConscript.ble_bootloader | 349 + core/SConscript.ble_firmware | 508 + core/SConstruct | 2 + core/embed/ble_bootloader/dfu/dfu-cc.options | 5 + core/embed/ble_bootloader/dfu/dfu-cc.pb.c | 30 + core/embed/ble_bootloader/dfu/dfu-cc.pb.h | 228 + core/embed/ble_bootloader/dfu/dfu-cc.proto | 69 + core/embed/ble_bootloader/dfu/nrf_dfu.c | 98 + core/embed/ble_bootloader/dfu/nrf_dfu.h | 85 + core/embed/ble_bootloader/dfu/nrf_dfu_flash.c | 167 + core/embed/ble_bootloader/dfu/nrf_dfu_flash.h | 132 + .../dfu/nrf_dfu_handling_error.c | 61 + .../dfu/nrf_dfu_handling_error.h | 125 + core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c | 105 + core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h | 90 + .../ble_bootloader/dfu/nrf_dfu_req_handler.c | 864 + .../ble_bootloader/dfu/nrf_dfu_req_handler.h | 346 + .../ble_bootloader/dfu/nrf_dfu_settings.c | 423 + .../ble_bootloader/dfu/nrf_dfu_settings.h | 212 + .../dfu/nrf_dfu_settings_svci.c | 185 + core/embed/ble_bootloader/dfu/nrf_dfu_svci.c | 87 + .../ble_bootloader/dfu/nrf_dfu_svci_handler.c | 212 + .../ble_bootloader/dfu/nrf_dfu_transport.c | 91 + .../ble_bootloader/dfu/nrf_dfu_transport.h | 134 + .../ble_bootloader/dfu/nrf_dfu_trigger_usb.c | 244 + .../ble_bootloader/dfu/nrf_dfu_trigger_usb.h | 74 + core/embed/ble_bootloader/dfu/nrf_dfu_types.h | 342 + core/embed/ble_bootloader/dfu/nrf_dfu_utils.c | 220 + core/embed/ble_bootloader/dfu/nrf_dfu_utils.h | 154 + .../ble_bootloader/dfu/nrf_dfu_validation.c | 986 + .../ble_bootloader/dfu/nrf_dfu_validation.h | 199 + .../dfu/nrf_dfu_ver_validation.c | 311 + .../dfu/nrf_dfu_ver_validation.h | 64 + core/embed/ble_bootloader/dfu_public_key.c | 20 + core/embed/ble_bootloader/jlink.jdebug | 332 + core/embed/ble_bootloader/main.c | 169 + core/embed/ble_bootloader/memory.ld | 156 + core/embed/ble_bootloader/nrf_bootloader.c | 465 + .../ble_bootloader/nrf_crypto_allocator.h | 63 + .../ble_bootloader/nrf_dfu_serial_uart.c | 276 + core/embed/ble_bootloader/priv.pem | 5 + core/embed/ble_bootloader/sdk_config.h | 5307 ++++ core/embed/ble_bootloader/settings.hex | 104 + core/embed/ble_bootloader/version.h | 4 + core/embed/ble_firmware/advertising.c | 203 + core/embed/ble_firmware/advertising.h | 18 + core/embed/ble_firmware/ble_nus.c | 356 + core/embed/ble_firmware/connection.c | 17 + core/embed/ble_firmware/connection.h | 11 + core/embed/ble_firmware/defs.h | 3 + core/embed/ble_firmware/dis.c | 23 + core/embed/ble_firmware/dis.h | 6 + core/embed/ble_firmware/int_comm.c | 596 + core/embed/ble_firmware/int_comm.h | 27 + core/embed/ble_firmware/jlink.jdebug | 332 + core/embed/ble_firmware/main.c | 627 + core/embed/ble_firmware/memory.ld | 139 + core/embed/ble_firmware/pm.c | 158 + core/embed/ble_firmware/pm.h | 18 + core/embed/ble_firmware/power.c | 21 + core/embed/ble_firmware/power.h | 6 + core/embed/ble_firmware/sdk_config.h | 12147 +++++++ core/embed/ble_firmware/uecc/.gitignore | 11 + core/embed/ble_firmware/uecc/LICENSE.txt | 21 + core/embed/ble_firmware/uecc/README.md | 41 + core/embed/ble_firmware/uecc/asm_arm.inc | 820 + .../ble_firmware/uecc/asm_arm_mult_square.inc | 2311 ++ .../uecc/asm_arm_mult_square_umaal.inc | 1202 + core/embed/ble_firmware/uecc/asm_avr.inc | 1089 + .../ble_firmware/uecc/asm_avr_mult_square.inc | 26311 ++++++++++++++++ .../ble_firmware/uecc/curve-specific.inc | 1248 + core/embed/ble_firmware/uecc/emk_project.py | 132 + core/embed/ble_firmware/uecc/emk_rules.py | 3 + .../uecc/examples/ecc_test/ecc_test.ino | 80 + .../ble_firmware/uecc/library.properties | 9 + .../ble_firmware/uecc/platform-specific.inc | 94 + .../ble_firmware/uecc/scripts/mult_arm.py | 188 + .../ble_firmware/uecc/scripts/mult_avr.py | 203 + .../uecc/scripts/mult_avr_extra.py | 143 + .../ble_firmware/uecc/scripts/square_arm.py | 242 + .../ble_firmware/uecc/scripts/square_avr.py | 327 + .../uecc/test/ecdsa_test_vectors.c | 128 + .../embed/ble_firmware/uecc/test/emk_rules.py | 4 + .../uecc/test/public_key_test_vectors.c | 338 + .../ble_firmware/uecc/test/test_compress.c | 79 + .../ble_firmware/uecc/test/test_compute.c | 81 + core/embed/ble_firmware/uecc/test/test_ecdh.c | 90 + .../embed/ble_firmware/uecc/test/test_ecdsa.c | 59 + .../test/test_ecdsa_deterministic.c.example | 93 + core/embed/ble_firmware/uecc/types.h | 108 + core/embed/ble_firmware/uecc/uECC.c | 1669 + core/embed/ble_firmware/uecc/uECC.h | 367 + core/embed/ble_firmware/uecc/uECC_vli.h | 172 + core/embed/ble_firmware/version.h | 4 + core/site_scons/tools.py | 19 + core/tools/convert_ble_firmware.py | 35 + core/tools/generate_ble_bl_settings.sh | 1 + tools/style.c.exclude | 3 + 100 files changed, 66580 insertions(+), 1 deletion(-) create mode 100644 core/SConscript.ble_bootloader create mode 100644 core/SConscript.ble_firmware create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.options create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.pb.c create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.pb.h create mode 100644 core/embed/ble_bootloader/dfu/dfu-cc.proto create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_flash.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_flash.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_svci.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_transport.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_transport.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_types.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_utils.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_utils.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_validation.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_validation.h create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c create mode 100644 core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h create mode 100644 core/embed/ble_bootloader/dfu_public_key.c create mode 100644 core/embed/ble_bootloader/jlink.jdebug create mode 100644 core/embed/ble_bootloader/main.c create mode 100644 core/embed/ble_bootloader/memory.ld create mode 100644 core/embed/ble_bootloader/nrf_bootloader.c create mode 100644 core/embed/ble_bootloader/nrf_crypto_allocator.h create mode 100644 core/embed/ble_bootloader/nrf_dfu_serial_uart.c create mode 100644 core/embed/ble_bootloader/priv.pem create mode 100644 core/embed/ble_bootloader/sdk_config.h create mode 100644 core/embed/ble_bootloader/settings.hex create mode 100644 core/embed/ble_bootloader/version.h create mode 100644 core/embed/ble_firmware/advertising.c create mode 100644 core/embed/ble_firmware/advertising.h create mode 100644 core/embed/ble_firmware/ble_nus.c create mode 100644 core/embed/ble_firmware/connection.c create mode 100644 core/embed/ble_firmware/connection.h create mode 100644 core/embed/ble_firmware/defs.h create mode 100644 core/embed/ble_firmware/dis.c create mode 100644 core/embed/ble_firmware/dis.h create mode 100644 core/embed/ble_firmware/int_comm.c create mode 100644 core/embed/ble_firmware/int_comm.h create mode 100644 core/embed/ble_firmware/jlink.jdebug create mode 100644 core/embed/ble_firmware/main.c create mode 100644 core/embed/ble_firmware/memory.ld create mode 100644 core/embed/ble_firmware/pm.c create mode 100644 core/embed/ble_firmware/pm.h create mode 100644 core/embed/ble_firmware/power.c create mode 100644 core/embed/ble_firmware/power.h create mode 100644 core/embed/ble_firmware/sdk_config.h create mode 100644 core/embed/ble_firmware/uecc/.gitignore create mode 100644 core/embed/ble_firmware/uecc/LICENSE.txt create mode 100644 core/embed/ble_firmware/uecc/README.md create mode 100644 core/embed/ble_firmware/uecc/asm_arm.inc create mode 100644 core/embed/ble_firmware/uecc/asm_arm_mult_square.inc create mode 100644 core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc create mode 100644 core/embed/ble_firmware/uecc/asm_avr.inc create mode 100644 core/embed/ble_firmware/uecc/asm_avr_mult_square.inc create mode 100644 core/embed/ble_firmware/uecc/curve-specific.inc create mode 100644 core/embed/ble_firmware/uecc/emk_project.py create mode 100644 core/embed/ble_firmware/uecc/emk_rules.py create mode 100644 core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino create mode 100644 core/embed/ble_firmware/uecc/library.properties create mode 100644 core/embed/ble_firmware/uecc/platform-specific.inc create mode 100755 core/embed/ble_firmware/uecc/scripts/mult_arm.py create mode 100755 core/embed/ble_firmware/uecc/scripts/mult_avr.py create mode 100755 core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py create mode 100755 core/embed/ble_firmware/uecc/scripts/square_arm.py create mode 100755 core/embed/ble_firmware/uecc/scripts/square_avr.py create mode 100644 core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c create mode 100644 core/embed/ble_firmware/uecc/test/emk_rules.py create mode 100644 core/embed/ble_firmware/uecc/test/public_key_test_vectors.c create mode 100644 core/embed/ble_firmware/uecc/test/test_compress.c create mode 100644 core/embed/ble_firmware/uecc/test/test_compute.c create mode 100644 core/embed/ble_firmware/uecc/test/test_ecdh.c create mode 100644 core/embed/ble_firmware/uecc/test/test_ecdsa.c create mode 100644 core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example create mode 100644 core/embed/ble_firmware/uecc/types.h create mode 100644 core/embed/ble_firmware/uecc/uECC.c create mode 100644 core/embed/ble_firmware/uecc/uECC.h create mode 100644 core/embed/ble_firmware/uecc/uECC_vli.h create mode 100644 core/embed/ble_firmware/version.h create mode 100644 core/tools/convert_ble_firmware.py create mode 100644 core/tools/generate_ble_bl_settings.sh diff --git a/core/.gitignore b/core/.gitignore index 25c2107f2..e7d93b2e5 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -11,3 +11,5 @@ mypy_report /CMakeLists.txt /cmake-build-debug/ tools/gdb_scripts/*.log +/embed/ble_bootloader/jlink.jdebug.user +/embed/ble_firmware/jlink.jdebug.user diff --git a/core/Makefile b/core/Makefile index ddae3d331..e60f4936c 100644 --- a/core/Makefile +++ b/core/Makefile @@ -5,6 +5,8 @@ MAKE = make -j $(JOBS) SCONS = scons -Q -j $(JOBS) BUILD_DIR = build +BLE_BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/ble_bootloader +BLE_FIRMWARE_BUILD_DIR = $(BUILD_DIR)/ble_firmware BOARDLOADER_BUILD_DIR = $(BUILD_DIR)/boardloader BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci @@ -172,6 +174,13 @@ build: build_boardloader build_bootloader build_firmware build_prodtest build_un build_embed: build_boardloader build_bootloader build_firmware # build boardloader, bootloader, firmware + +build_ble_bootloader: ## build ble_bootloader + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.bin + +build_ble_firmware: ## build ble_firmware + $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware.bin + build_boardloader: ## build boardloader $(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" \ CMAKELISTS="$(CMAKELISTS)" $(BOARDLOADER_BUILD_DIR)/boardloader.bin @@ -226,9 +235,16 @@ build_cross: ## build mpy-cross port ## clean commands: -clean: clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all +clean: clean_ble_bootloader clean_ble_firmware clean_boardloader clean_bootloader clean_bootloader_emu clean_bootloader_ci clean_prodtest clean_reflash clean_firmware clean_unix clean_cross ## clean all rm -f ".sconsign.dblite" + +clean_ble_bootloader: ## clean ble_bootloader build + rm -rf $(BLE_BOOTLOADER_BUILD_DIR) + +clean_ble_firmware: ## clean ble_bootloader build + rm -rf $(BLE_FIRMWARE_BUILD_DIR) + clean_boardloader: ## clean boardloader build rm -rf $(BOARDLOADER_BUILD_DIR) @@ -260,6 +276,24 @@ clean_cross: ## clean mpy-cross build flash: flash_boardloader flash_bootloader flash_firmware ## flash everything using OpenOCD +flash_ble: flash_ble_bootloader flash_softdevice flash_ble_firmware + +flash_ble_bootloader: + @echo Flashing: $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.hex + nrfjprog -f nrf52 --program $(BLE_BOOTLOADER_BUILD_DIR)/ble_bootloader.hex --sectorerase + +flash_ble_firmware: + @echo Flashing: $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware_merged.hex + nrfjprog -f nrf52 --program $(BLE_FIRMWARE_BUILD_DIR)/ble_firmware_merged.hex --sectorerase + +flash_ble_bl_settings: + @echo Flashing: $(BLE_BOOTLOADER_BUILD_DIR)/settings.hex + nrfjprog -f nrf52 --program $(BLE_BOOTLOADER_BUILD_DIR)/settings.hex --sectorerase + +flash_softdevice: + @echo Flashing: s140_nrf52_7.2.0_softdevice.hex + nrfjprog -f nrf52 --program embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --sectorerase + flash_boardloader: $(BOARDLOADER_BUILD_DIR)/boardloader.bin ## flash boardloader using OpenOCD $(OPENOCD) -c "init; reset halt; flash write_image erase $< $(BOARDLOADER_START); exit" @@ -284,6 +318,9 @@ flash_combine: $(PRODTEST_BUILD_DIR)/combined.bin ## flash combined using OpenOC flash_erase: ## erase all sectors in flash bank 0 $(OPENOCD) -c "init; reset halt; flash info 0; flash erase_sector 0 0 last; flash erase_check 0; exit" +flash_erase_ble: + nrfjprog -f nrf52 --eraseall + flash_read_storage: ## read storage sectors from flash $(OPENOCD) -c "init; flash read_bank 0 storage1.data 0x10000 65536; flash read_bank 0 storage2.data 0x110000 65536; exit" @@ -312,6 +349,10 @@ openocd: ## start openocd which connects to the device openocd_reset: ## cause a system reset using OpenOCD $(OPENOCD) -c "init; reset; exit" +# nrfjprog debug commands: +nrfjprog_reset: + nrfjprog -f nrf52 --reset + GDB = arm-none-eabi-gdb --nx -ex 'set remotetimeout unlimited' -ex 'set confirm off' -ex 'target remote 127.0.0.1:3333' -ex 'monitor reset halt' gdb_boardloader: $(BOARDLOADER_BUILD_DIR)/boardloader.elf ## start remote gdb session to openocd with boardloader symbols diff --git a/core/SConscript.ble_bootloader b/core/SConscript.ble_bootloader new file mode 100644 index 000000000..2114b2f3f --- /dev/null +++ b/core/SConscript.ble_bootloader @@ -0,0 +1,349 @@ +# pylint: disable=E0602 + +import os +import tools + +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) + +if TREZOR_MODEL in ('1', ): + # skip boardloader build + env = Environment() + def build_ble_bootloader(target,source,env): + print(f'BLE BOOTLOADER: nothing to build for Model {TREZOR_MODEL}') + program_bin = env.Command( + target='ble_bootloader.bin', + source=None, + action=build_ble_bootloader + ) + Return() + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] + +CCFLAGS_MOD += '-Wno-sequence-point ' + + +if int(ARGUMENTS.get('PRODUCTION', 0)) == 0: + # Build for monitor debug mode and RTT. + DEBUG = True +else: + DEBUG = False + + + +# C flags common to all targets +CPPDEFINES_MOD += [ + 'CONFIG_GPIO_AS_PINRESET', + 'FLOAT_ABI_HARD', + 'NRF52833_XXAA', + ('NRF_DFU_SETTINGS_VERSION','2'), + 'MBR_PRESENT', + 'SVC_INTERFACE_CALL_AS_NORMAL_FUNCTION', + ('__HEAP_SIZE','0'), + '__STARTUP_CLEAR_BSS', + ('__START', 'main'), + + ('uECC_ENABLE_VLI_API', '0'), + ('uECC_OPTIMIZATION_LEVEL', '3'), + ('uECC_SQUARE_FUNC', '0'), + ('uECC_SUPPORT_COMPRESSED_POINT', '0'), + ('uECC_VLI_NATIVE_LITTLE_ENDIAN', '1'), + + + 'ED25519_NO_PRECOMP', +] + + + + +CPPPATH_MOD += [ +] +CPPDEFINES_MOD += [ +] +SOURCE_MOD += [ + +] + +CPPPATH_MOD += [ + 'embed/sdk/nrf52/modules/nrfx/drivers/include', + 'embed/sdk/nrf52/components/libraries/memobj', + 'embed/sdk/nrf52/components/libraries/crc32', + 'embed/sdk/nrf52/components/libraries/experimental_section_vars', + 'embed/sdk/nrf52/components/libraries/mem_manager', + 'embed/sdk/nrf52/components/libraries/fstorage', + 'embed/sdk/nrf52/components/libraries/util', + 'embed/sdk/nrf52/modules/nrfx', + 'embed/sdk/nrf52/external/nrf_oberon/include', + 'embed/sdk/nrf52/components/libraries/atomic', + 'embed/sdk/nrf52/integration/nrfx', + 'embed/sdk/nrf52/components/libraries/crypto/backend/cc310_bl', + 'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd', + 'embed/sdk/nrf52/components/libraries/log/src', + 'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu', + 'embed/sdk/nrf52/external/segger_rtt', + 'embed/sdk/nrf52/components/libraries/delay', + 'embed/sdk/nrf52/integration/nrfx/legacy', + 'embed/sdk/nrf52/modules/nrfx/hal', + 'embed/sdk/nrf52/components/libraries/log', + 'embed/sdk/nrf52/components/libraries/strerror', + 'embed/sdk/nrf52/components/libraries/bootloader', + 'embed/sdk/nrf52/components/softdevice/mbr/headers', + 'embed/sdk/nrf52/components/libraries/scheduler', + 'embed/sdk/nrf52/components/libraries/slip', + 'embed/sdk/nrf52/external/fprintf', + 'embed/sdk/nrf52/components/toolchain/cmsis/include', + 'embed/sdk/nrf52/components/libraries/balloc', + 'embed/sdk/nrf52/components/libraries/stack_info', + 'embed/sdk/nrf52/modules/nrfx/mdk', + 'embed/sdk/nrf52/components/libraries/queue', + 'embed/sdk/nrf52/components/libraries/mutex', + 'embed/sdk/nrf52/components/libraries/ringbuf', + + + 'embed/trezorhal/boards', + 'embed/lib', + + 'vendor/trezor-crypto', + 'vendor/nanopb', +] +SOURCE_MOD += [ +] + + +SOURCE_NRFHAL_AS = [ + 'embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S', +] + + + +SOURCE_NRFHAL = [ + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_frontend.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_str_formatter.c', + 'embed/sdk/nrf52/modules/nrfx/mdk/system_nrf52833.c', + 'embed/sdk/nrf52/components/libraries/util/app_error_weak.c', + 'embed/sdk/nrf52/components/libraries/scheduler/app_scheduler.c', + 'embed/sdk/nrf52/components/libraries/util/app_util_platform.c', + 'embed/sdk/nrf52/components/libraries/crc32/crc32.c', + 'embed/sdk/nrf52/components/libraries/mem_manager/mem_manager.c', + 'embed/sdk/nrf52/components/libraries/util/nrf_assert.c', + 'embed/sdk/nrf52/components/libraries/atomic/nrf_atomic.c', + 'embed/sdk/nrf52/components/libraries/balloc/nrf_balloc.c', + 'embed/sdk/nrf52/external/fprintf/nrf_fprintf.c', + 'embed/sdk/nrf52/external/fprintf/nrf_fprintf_format.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_nvmc.c', + 'embed/sdk/nrf52/components/libraries/memobj/nrf_memobj.c', + 'embed/sdk/nrf52/components/libraries/queue/nrf_queue.c', + 'embed/sdk/nrf52/components/libraries/ringbuf/nrf_ringbuf.c', + 'embed/sdk/nrf52/components/libraries/strerror/nrf_strerror.c', + 'embed/sdk/nrf52/components/libraries/slip/slip.c', + 'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_uart.c', + 'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c', + 'embed/sdk/nrf52/modules/nrfx/hal/nrf_nvmc.c', + 'embed/sdk/nrf52/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c', + 'embed/sdk/nrf52/modules/nrfx/soc/nrfx_atomic.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/prs/nrfx_prs.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uart.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uarte.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_app_start.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_app_start_final.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_dfu_timers.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_fw_activation.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_info.c', + 'embed/sdk/nrf52/components/libraries/bootloader/nrf_bootloader_wdt.c', + 'embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial.c', +] + +SOURCE_BLE_BOOTLOADER = [ + 'embed/ble_bootloader/main.c', + 'embed/ble_bootloader/dfu_public_key.c', + # originally embed/sdk/nrf52/components/libraries/bootloader/serial_dfu/nrf_dfu_serial_uart.c', + 'embed/ble_bootloader/nrf_dfu_serial_uart.c', + 'embed/ble_bootloader/nrf_bootloader.c', + # ejected from embed/sdk/nrf52/components/libraries/bootloader/dfu + 'embed/ble_bootloader/dfu/nrf_dfu_validation.c', + 'embed/ble_bootloader/dfu/dfu-cc.pb.c', + 'embed/ble_bootloader/dfu/nrf_dfu.c', + 'embed/ble_bootloader/dfu/nrf_dfu_flash.c', + 'embed/ble_bootloader/dfu/nrf_dfu_handling_error.c', + 'embed/ble_bootloader/dfu/nrf_dfu_mbr.c', + 'embed/ble_bootloader/dfu/nrf_dfu_req_handler.c', + 'embed/ble_bootloader/dfu/nrf_dfu_settings.c', + 'embed/ble_bootloader/dfu/nrf_dfu_transport.c', + 'embed/ble_bootloader/dfu/nrf_dfu_utils.c', + 'embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c', + + 'vendor/trezor-crypto/blake2s.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c', + 'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c', + 'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c', + 'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c', + 'vendor/trezor-crypto/memzero.c', + 'vendor/trezor-crypto/sha2.c', + + 'vendor/nanopb/pb_common.c', + 'vendor/nanopb/pb_decode.c', + 'vendor/nanopb/pb_encode.c', +] + +if DEBUG: + CPPDEFINES_MOD += [ + 'DEBUG', + 'DEBUG_NRF', + 'NRF_DFU_DEBUG_VERSION', + 'MMD' + ] + SOURCE_BLE_BOOTLOADER += [ + 'embed/segger/SEGGER_MMD/JLINK_MONITOR.c', + 'embed/segger/SEGGER_MMD/JLINK_MONITOR_ISR_SES.S' + ] + + SOURCE_NRFHAL += [ + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_rtt.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_serial.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_uart.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_default_backends.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_printf.c', + ] + + + CPPPATH_MOD += [ + 'embed/segger/SEGGER_MMD' + ] + + + +env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0'))) + + +env.Replace( + CP='cp', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', + PYTHON='python', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL, ) + +CPU_ASFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' +CPU_CCFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 ' + + + + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), + CCFLAGS='$COPT ' + '-g3 ' + '-nostdlib ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' + '-fdata-sections -ffunction-sections ' + '-fno-strict-aliasing ' + '-fno-builtin ' + '-fshort-enums ' + + CPU_CCFLAGS + CCFLAGS_MOD, + LINKFLAGS='-Lembed/sdk/nrf52/modules/nrfx/mdk -T embed/ble_bootloader/memory.ld -Wl,--gc-sections --specs=nano.specs -Wl,-Map=build/ble_bootloader/ble_bootloader.map -Wl,--warn-common -Wl,--print-memory-usage', + CPPPATH=[ + 'embed/ble_bootloader', + 'embed/ble_bootloader/dfu', + 'embed/sdk/nrf52', + ] + CPPPATH_MOD, + CPPDEFINES=[ + 'BLE_BOOTLOADER', + 'TREZOR_MODEL_'+TREZOR_MODEL, + ] + CPPDEFINES_MOD, + ASFLAGS=CPU_ASFLAGS, + ASPPFLAGS='$CFLAGS $CCFLAGS', ) + +# +# Program objects +# + +obj_program = [] +obj_program += env.Object(source=SOURCE_BLE_BOOTLOADER) +obj_program += env.Object(source=SOURCE_NRFHAL_AS, COPT='-O0') +obj_program += env.Object(source=SOURCE_NRFHAL) +obj_program += env.Object(source=SOURCE_MOD) + +env.Replace( + ALLSOURCES=SOURCE_NRFHAL_AS + SOURCE_MOD + SOURCE_BLE_BOOTLOADER + SOURCE_NRFHAL, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'])) + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + + +LIB_FILES = [ +] + +program_elf = env.Command( + target='ble_bootloader.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES ' + ' '.join(LIB_FILES) + ' -lc -lnosys -lm', +) + + + +BINARY_NAME = f"build/ble_bootloader/ble_bootloader-{tools.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME += "-" + tools.get_version('embed/ble_bootloader/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + + + +program_hex = env.Command( + target='ble_bootloader.hex', + source=program_elf, + action='$OBJCOPY -O ihex $SOURCE $TARGET', +) + +program_bin = env.Command( + target='ble_bootloader.bin', + source=program_elf, + action=[ + '$OBJCOPY -O binary $SOURCE $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ], +) + + +bootloader_pkg = env.Command( + target='ble_bootloader.zip', + source=program_hex, + action=[ + f'python ../../pc-nrfutil/nordicsemi/ pkg generate --hw-version 52 --sd-req=0x100 --key-file ./embed/ble_bootloader/priv.pem $TARGET --bootloader $SOURCE --bootloader-version {tools.get_version_int("embed/ble_bootloader/version.h")}' + ], +) + + + +program_settings = env.Command( + target='settings.hex', + source=None, + action='$CP ./embed/ble_bootloader/settings.hex $TARGET', +) + +env.Depends(program_bin, program_hex) +env.Depends(program_bin, bootloader_pkg) +env.Depends(program_bin, program_settings) diff --git a/core/SConscript.ble_firmware b/core/SConscript.ble_firmware new file mode 100644 index 000000000..ddca18525 --- /dev/null +++ b/core/SConscript.ble_firmware @@ -0,0 +1,508 @@ +# pylint: disable=E0602 + +import os +import tools + +TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T') +CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0)) + +if TREZOR_MODEL in ('1', ): + # skip boardloader build + env = Environment() + def build_ble_firmware(target,source,env): + print(f'BLE FIRMWARE: nothing to build for Model {TREZOR_MODEL}') + program_bin = env.Command( + target='ble_firmware.bin', + source=None, + action=build_ble_firmware + ) + Return() + +CCFLAGS_MOD = '' +CPPPATH_MOD = [] +CPPDEFINES_MOD = [] +SOURCE_MOD = [] + +CCFLAGS_MOD += '-Wno-sequence-point ' + + +if int(ARGUMENTS.get('PRODUCTION', 0)) == 0: + # Build for monitor debug mode. + MMD = True +else: + MMD = False + + + +# C flags common to all targets +CPPDEFINES_MOD += [ + 'CONFIG_GPIO_AS_PINRESET', + 'FLOAT_ABI_HARD', + 'NRF52833_XXAA', + 'SOFTDEVICE_PRESENT', + ('NRF_SD_BLE_API_VERSION', '7'), + 'APP_TIMER_V2', + 'APP_TIMER_V2_RTC1_ENABLED', + 'S140', + ('__HEAP_SIZE','8192'), + ('__STACK_SIZE','8192'), + '__STARTUP_CLEAR_BSS', + ('__START', 'main'), + + ('uECC_ENABLE_VLI_API', '0'), + ('uECC_OPTIMIZATION_LEVEL', '3'), + ('uECC_SQUARE_FUNC', '0'), + ('uECC_SUPPORT_COMPRESSED_POINT', '0'), + ('uECC_VLI_NATIVE_LITTLE_ENDIAN', '1'), +] + + + +CPPPATH_MOD += [ +] +CPPDEFINES_MOD += [ +] +SOURCE_MOD += [ + +] + +CPPPATH_MOD += [ + 'embed/sdk/nrf52/components/nfc/ndef/generic/message', + 'embed/sdk/nrf52/components/nfc/t2t_lib', + 'embed/sdk/nrf52/components/nfc/t4t_parser/hl_detection_procedure', + 'embed/sdk/nrf52/components/ble/ble_services/ble_ancs_c', + 'embed/sdk/nrf52/components/ble/ble_services/ble_ias_c', + 'embed/sdk/nrf52/components/libraries/pwm', + 'embed/sdk/nrf52/components/libraries/usbd/class/cdc/acm', + 'embed/sdk/nrf52/components/libraries/usbd/class/hid/generic', + 'embed/sdk/nrf52/components/libraries/usbd/class/msc', + 'embed/sdk/nrf52/components/libraries/usbd/class/hid', + 'embed/sdk/nrf52/modules/nrfx/hal', + 'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/le_oob_rec_parser', + 'embed/sdk/nrf52/components/libraries/log', + 'embed/sdk/nrf52/components/ble/ble_services/ble_gls', + 'embed/sdk/nrf52/components/libraries/fstorage', + 'embed/sdk/nrf52/components/nfc/ndef/text', + 'embed/sdk/nrf52/components/libraries/mutex', + 'embed/sdk/nrf52/components/libraries/gfx', + 'embed/sdk/nrf52/components/libraries/bootloader/ble_dfu', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/common', + 'embed/sdk/nrf52/components/libraries/fifo', + 'embed/sdk/nrf52/components/nfc/ndef/generic/record', + 'embed/sdk/nrf52/components/nfc/t4t_parser/cc_file', + 'embed/sdk/nrf52/components/ble/ble_advertising', + 'embed/sdk/nrf52/external/utf_converter', + 'embed/sdk/nrf52/components/ble/ble_services/ble_bas_c', + 'embed/sdk/nrf52/modules/nrfx/drivers/include', + 'embed/sdk/nrf52/components/libraries/experimental_task_manager', + 'embed/sdk/nrf52/components/ble/ble_services/ble_hrs_c', + 'embed/sdk/nrf52/components/softdevice/s140/headers/nrf52', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/le_oob_rec', + 'embed/sdk/nrf52/components/libraries/queue', + 'embed/sdk/nrf52/components/libraries/pwr_mgmt', + 'embed/sdk/nrf52/components/ble/ble_dtm', + 'embed/sdk/nrf52/components/toolchain/cmsis/include', + 'embed/sdk/nrf52/components/ble/ble_services/ble_rscs_c', + 'embed/sdk/nrf52/components/ble/common', + 'embed/sdk/nrf52/components/ble/ble_services/ble_lls', + 'embed/sdk/nrf52/components/nfc/platform', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ac_rec', + 'embed/sdk/nrf52/components/ble/ble_services/ble_bas', + 'embed/sdk/nrf52/components/libraries/mpu', + 'embed/sdk/nrf52/components/libraries/experimental_section_vars', + 'embed/sdk/nrf52/components/ble/ble_services/ble_ans_c', + 'embed/sdk/nrf52/components/libraries/slip', + 'embed/sdk/nrf52/components/libraries/delay', + 'embed/sdk/nrf52/components/libraries/csense_drv', + 'embed/sdk/nrf52/components/libraries/memobj', + 'embed/sdk/nrf52/components/ble/ble_services/ble_nus_c', + 'embed/sdk/nrf52/components/softdevice/common', + 'embed/sdk/nrf52/components/ble/ble_services/ble_ias', + 'embed/sdk/nrf52/components/libraries/usbd/class/hid/mouse', + 'embed/sdk/nrf52/components/libraries/low_power_pwm', + 'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/ble_oob_advdata_parser', + 'embed/sdk/nrf52/components/ble/ble_services/ble_dfu', + 'embed/sdk/nrf52/external/fprintf', + 'embed/sdk/nrf52/components/libraries/svc', + 'embed/sdk/nrf52/components/libraries/atomic', + 'embed/sdk/nrf52/components', + 'embed/sdk/nrf52/components/libraries/scheduler', + 'embed/sdk/nrf52/components/libraries/cli', + 'embed/sdk/nrf52/components/ble/ble_services/ble_lbs', + 'embed/sdk/nrf52/components/ble/ble_services/ble_hts', + 'embed/sdk/nrf52/components/ble/ble_services/ble_cts_c', + 'embed/sdk/nrf52/components/libraries/crc16', + 'embed/sdk/nrf52/components/nfc/t4t_parser/apdu', + 'embed/sdk/nrf52/components/libraries/util', + 'embed/sdk/nrf52/components/libraries/usbd/class/cdc', + 'embed/sdk/nrf52/components/libraries/csense', + 'embed/sdk/nrf52/components/libraries/balloc', + 'embed/sdk/nrf52/components/libraries/ecc', + 'embed/sdk/nrf52/components/libraries/hardfault', + 'embed/sdk/nrf52/components/ble/ble_services/ble_cscs', + 'embed/sdk/nrf52/components/libraries/uart', + 'embed/sdk/nrf52/components/libraries/hci', + 'embed/sdk/nrf52/components/libraries/usbd/class/hid/kbd', + 'embed/sdk/nrf52/components/libraries/timer', + 'embed/sdk/nrf52/components/libraries/queue', + 'embed/sdk/nrf52/components/softdevice/s140/headers', + 'embed/sdk/nrf52/integration/nrfx', + 'embed/sdk/nrf52/components/nfc/t4t_parser/tlv', + 'embed/sdk/nrf52/components/libraries/sortlist', + 'embed/sdk/nrf52/components/libraries/spi_mngr', + 'embed/sdk/nrf52/components/libraries/led_softblink', + 'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser', + 'embed/sdk/nrf52/components/libraries/sdcard', + 'embed/sdk/nrf52/components/nfc/ndef/parser/record', + 'embed/sdk/nrf52/modules/nrfx/mdk', + 'embed/sdk/nrf52/components/ble/ble_link_ctx_manager', + 'embed/sdk/nrf52/components/ble/ble_services/ble_nus', + 'embed/sdk/nrf52/components/libraries/twi_mngr', + 'embed/sdk/nrf52/components/ble/ble_services/ble_hids', + 'embed/sdk/nrf52/components/libraries/strerror', + 'embed/sdk/nrf52/components/libraries/crc32', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_oob_advdata', + 'embed/sdk/nrf52/components/nfc/t2t_parser', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_pair_msg', + 'embed/sdk/nrf52/components/libraries/usbd/class/audio', + 'embed/sdk/nrf52/components/nfc/t4t_lib', + 'embed/sdk/nrf52/components/ble/peer_manager', + 'embed/sdk/nrf52/components/libraries/mem_manager', + 'embed/sdk/nrf52/components/libraries/ringbuf', + 'embed/sdk/nrf52/components/ble/ble_services/ble_tps', + 'embed/sdk/nrf52/components/nfc/ndef/parser/message', + 'embed/sdk/nrf52/components/ble/ble_services/ble_dis', + 'embed/sdk/nrf52/components/nfc/ndef/uri', + 'embed/sdk/nrf52/components/ble/nrf_ble_gatt', + 'embed/sdk/nrf52/components/ble/nrf_ble_qwr', + 'embed/sdk/nrf52/components/libraries/gpiote', + 'embed/sdk/nrf52/components/libraries/button', + 'embed/sdk/nrf52/modules/nrfx', + 'embed/sdk/nrf52/components/libraries/twi_sensor', + 'embed/sdk/nrf52/integration/nrfx/legacy', + 'embed/sdk/nrf52/components/libraries/usbd', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ep_oob_rec', + 'embed/sdk/nrf52/external/segger_rtt', + 'embed/sdk/nrf52/components/libraries/atomic_fifo', + 'embed/sdk/nrf52/components/ble/ble_services/ble_lbs_c', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/ble_pair_lib', + 'embed/sdk/nrf52/components/libraries/crypto', + 'embed/sdk/nrf52/components/libraries/crypto/backend/cc310', + 'embed/sdk/nrf52/components/libraries/crypto/backend/cc310_bl', + 'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc', + 'embed/sdk/nrf52/components/libraries/crypto/backend/mbedtls', + 'embed/sdk/nrf52/components/libraries/crypto/backend/oberon', + 'embed/sdk/nrf52/components/libraries/crypto/backend/optiga', + 'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_sw', + 'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw', + 'embed/sdk/nrf52/components/libraries/crypto/backend/cifra', + 'embed/sdk/nrf52/components/ble/ble_racp', + 'embed/sdk/nrf52/components/libraries/fds', + 'embed/sdk/nrf52/components/nfc/ndef/launchapp', + 'embed/sdk/nrf52/components/libraries/atomic_flags', + 'embed/sdk/nrf52/components/ble/ble_services/ble_hrs', + 'embed/sdk/nrf52/components/ble/ble_services/ble_rscs', + 'embed/sdk/nrf52/components/nfc/ndef/connection_handover/hs_rec', + 'embed/sdk/nrf52/components/nfc/ndef/conn_hand_parser/ac_rec_parser', + 'embed/sdk/nrf52/components/libraries/stack_guard', + 'embed/sdk/nrf52/components/libraries/stack_info', + 'embed/sdk/nrf52/components/libraries/log/src', + 'embed/sdk/nrf52/external/mbedtls/include', + 'embed', + 'embed/trezorhal/boards', +] +SOURCE_MOD += [ +] + + +SOURCE_NRFHAL_AS = [ + 'embed/sdk/nrf52/modules/nrfx/mdk/gcc_startup_nrf52833.S', +] + + + +SOURCE_NRFHAL = [ + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_frontend.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_str_formatter.c', + 'embed/sdk/nrf52/components/libraries/button/app_button.c', + 'embed/sdk/nrf52/components/libraries/util/app_error.c', + 'embed/sdk/nrf52/components/libraries/util/app_error_handler_gcc.c', + 'embed/sdk/nrf52/components/libraries/util/app_error_weak.c', + 'embed/sdk/nrf52/components/libraries/fifo/app_fifo.c', + 'embed/sdk/nrf52/components/libraries/scheduler/app_scheduler.c', + 'embed/sdk/nrf52/components/libraries/timer/app_timer2.c', + 'embed/sdk/nrf52/components/libraries/uart/app_uart_fifo.c', + 'embed/sdk/nrf52/components/libraries/util/app_util_platform.c', + 'embed/sdk/nrf52/components/libraries/timer/drv_rtc.c', + 'embed/sdk/nrf52/components/libraries/hardfault/hardfault_implementation.c', + 'embed/sdk/nrf52/components/libraries/util/nrf_assert.c', + 'embed/sdk/nrf52/components/libraries/atomic_fifo/nrf_atfifo.c', + 'embed/sdk/nrf52/components/libraries/atomic_flags/nrf_atflags.c', + 'embed/sdk/nrf52/components/libraries/atomic/nrf_atomic.c', + 'embed/sdk/nrf52/components/libraries/balloc/nrf_balloc.c', + 'embed/sdk/nrf52/external/fprintf/nrf_fprintf.c', + 'embed/sdk/nrf52/external/fprintf/nrf_fprintf_format.c', + 'embed/sdk/nrf52/components/libraries/memobj/nrf_memobj.c', + 'embed/sdk/nrf52/components/libraries/pwr_mgmt/nrf_pwr_mgmt.c', + 'embed/sdk/nrf52/components/libraries/ringbuf/nrf_ringbuf.c', + 'embed/sdk/nrf52/components/libraries/experimental_section_vars/nrf_section_iter.c', + 'embed/sdk/nrf52/components/libraries/sortlist/nrf_sortlist.c', + 'embed/sdk/nrf52/components/libraries/strerror/nrf_strerror.c', + 'embed/sdk/nrf52/components/libraries/uart/retarget.c', + 'embed/sdk/nrf52/components/libraries/queue/nrf_queue.c', + 'embed/sdk/nrf52/modules/nrfx/mdk/system_nrf52833.c', + 'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_clock.c', + 'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_uart.c', + 'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_spi.c', + 'embed/sdk/nrf52/integration/nrfx/legacy/nrf_drv_rng.c', + 'embed/sdk/nrf52/modules/nrfx/soc/nrfx_atomic.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_clock.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_gpiote.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/prs/nrfx_prs.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uart.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_uarte.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_rng.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_spi.c', + 'embed/sdk/nrf52/modules/nrfx/drivers/src/nrfx_spim.c', + 'embed/sdk/nrf52/components/ble/common/ble_advdata.c', + 'embed/sdk/nrf52/components/ble/ble_advertising/ble_advertising.c', + 'embed/sdk/nrf52/components/ble/common/ble_conn_params.c', + 'embed/sdk/nrf52/components/ble/common/ble_conn_state.c', + 'embed/sdk/nrf52/components/ble/ble_link_ctx_manager/ble_link_ctx_manager.c', + 'embed/sdk/nrf52/components/ble/common/ble_srv_common.c', + 'embed/sdk/nrf52/components/ble/nrf_ble_gatt/nrf_ble_gatt.c', + 'embed/sdk/nrf52/components/ble/nrf_ble_qwr/nrf_ble_qwr.c', + 'embed/sdk/nrf52/external/utf_converter/utf.c', + 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh.c', + 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_ble.c', + 'embed/sdk/nrf52/components/softdevice/common/nrf_sdh_soc.c', + 'embed/sdk/nrf52/components/ble/peer_manager/gatt_cache_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/gatts_cache_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/id_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_data_storage.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_database.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_id.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/peer_manager_handler.c', + 'embed/sdk/nrf52/components/ble/peer_manager/pm_buffer.c', + 'embed/sdk/nrf52/components/ble/peer_manager/nrf_ble_lesc.c', + 'embed/sdk/nrf52/components/libraries/fds/fds.c', + 'embed/sdk/nrf52/components/ble/peer_manager/security_manager.c', + 'embed/sdk/nrf52/components/ble/peer_manager/security_dispatcher.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage.c', + 'embed/sdk/nrf52/components/libraries/fstorage/nrf_fstorage_sd.c', + 'embed/sdk/nrf52/components/ble/ble_services/ble_dis/ble_dis.c', + 'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecc.c', + 'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdh.c', + 'embed/sdk/nrf52/components/libraries/crypto/backend/micro_ecc/micro_ecc_backend_ecdsa.c', + 'embed/sdk/nrf52/components/libraries/crypto/backend/nrf_hw/nrf_hw_backend_rng_mbedtls.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecc.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecdsa.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_ecdh.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_hash.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_init.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_shared.c', + 'embed/sdk/nrf52/components/libraries/crypto/nrf_crypto_rng.c', + 'embed/sdk/nrf52/external/mbedtls/library/ctr_drbg.c', + 'embed/sdk/nrf52/external/mbedtls/library/aes.c', + 'embed/sdk/nrf52/external/mbedtls/library/platform.c', + 'embed/sdk/nrf52/external/mbedtls/library/platform_util.c', + +] + +SOURCE_NANOPB = [ + 'vendor/nanopb/pb_common.c', + 'vendor/nanopb/pb_decode.c', + 'vendor/nanopb/pb_encode.c', +] + +SOURCE_BLE_FIRMWARE = [ + 'embed/ble_firmware/main.c', + 'embed/ble_firmware/ble_nus.c', + 'embed/ble_firmware/int_comm.c', + 'embed/ble_firmware/dis.c', + 'embed/ble_firmware/pm.c', + 'embed/ble_firmware/power.c', + 'embed/ble_firmware/advertising.c', + 'embed/ble_firmware/connection.c', + 'embed/ble_firmware/uecc/uECC.c', + 'embed/bootloader/protob/messages.pb.c', + 'embed/lib/protob_helpers.c', +] + +if MMD: + CPPDEFINES_MOD += [ + 'DEBUG', + 'DEBUG_NRF', + 'MMD' + ] + SOURCE_BLE_FIRMWARE += [ + 'embed/segger/SEGGER_MMD/JLINK_MONITOR.c', + 'embed/segger/SEGGER_MMD/JLINK_MONITOR_ISR_SES.S' + ] + + SOURCE_NRFHAL += [ + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_rtt.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_serial.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_backend_uart.c', + 'embed/sdk/nrf52/components/libraries/log/src/nrf_log_default_backends.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c', + 'embed/sdk/nrf52/external/segger_rtt/SEGGER_RTT_printf.c', + ] + + + CPPPATH_MOD += [ + 'embed/segger/SEGGER_MMD' + ] + + + +env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0'))) + + +env.Replace( + CP='cp', + AS='arm-none-eabi-as', + AR='arm-none-eabi-ar', + CC='arm-none-eabi-gcc', + LINK='arm-none-eabi-gcc', + SIZE='arm-none-eabi-size', + STRIP='arm-none-eabi-strip', + OBJCOPY='arm-none-eabi-objcopy', + PYTHON='python', + MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', ) + +env.Replace( + TREZOR_MODEL=TREZOR_MODEL, ) + +CPU_ASFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16' +CPU_CCFLAGS = '-mthumb -mabi=aapcs -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 ' + + + + +env.Replace( + COPT=env.get('ENV').get('OPTIMIZE', '-Os'), + CCFLAGS='$COPT ' + '-g3 ' + '-std=gnu11 -Wall -Werror -Wdouble-promotion -Wpointer-arith -Wno-missing-braces -Wno-unused-function ' + '-fdata-sections -ffunction-sections ' + '-fno-strict-aliasing ' + '-fno-builtin ' + '-fshort-enums ' + + CPU_CCFLAGS + CCFLAGS_MOD, + LINKFLAGS='-Lembed/sdk/nrf52/modules/nrfx/mdk -T embed/ble_firmware/memory.ld -Wl,--gc-sections --specs=nano.specs -Wl,-Map=build/ble_firmware/ble_firmware.map -Wl,--warn-common -Wl,--print-memory-usage', + CPPPATH=[ + 'embed/ble_firmware', + 'embed/bootloader/protob', + 'embed/ble_bootloader/dfu', + 'embed/sdk/nrf52', + 'embed/lib', + 'vendor/nanopb', + 'embed/ble_firmware/uecc', + ] + CPPPATH_MOD, + CPPDEFINES=[ + 'BLE_FIRMWARE', + 'TREZOR_MODEL_'+TREZOR_MODEL, + ] + CPPDEFINES_MOD, + ASFLAGS=CPU_ASFLAGS, + ASPPFLAGS='$CFLAGS $CCFLAGS', ) + +# +# Program objects +# + +obj_program = [] +obj_program += env.Object(source=SOURCE_BLE_FIRMWARE) +obj_program += env.Object(source=SOURCE_NRFHAL_AS, COPT='-O0') +obj_program += env.Object(source=SOURCE_NRFHAL) +obj_program += env.Object(source=SOURCE_NANOPB) +obj_program += env.Object(source=SOURCE_MOD) + +env.Replace( + ALLSOURCES=SOURCE_NRFHAL_AS + SOURCE_MOD + SOURCE_BLE_FIRMWARE + SOURCE_NRFHAL, + ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES'])) + +cmake_gen = env.Command( + target='CMakeLists.txt', + source='', + action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS', +) + + +LIB_FILES = [ +] + +program_elf = env.Command( + target='ble_firmware.elf', + source=obj_program, + action= + '$LINK -o $TARGET $CCFLAGS $CFLAGS $LINKFLAGS $SOURCES ' + ' '.join(LIB_FILES) + ' -lc -lnosys -lm', +) + + + +BINARY_NAME = f"build/ble_firmware/ble_firmware-{tools.get_model_identifier(TREZOR_MODEL)}" +BINARY_NAME += "-" + tools.get_version('embed/ble_firmware/version.h') +BINARY_NAME += "-" + tools.get_git_revision_short_hash() +BINARY_NAME += "-dirty" if tools.get_git_modified() else "" +BINARY_NAME += ".bin" + +if CMAKELISTS != 0: + env.Depends(program_elf, cmake_gen) + + + +program_hex = env.Command( + target='ble_firmware.hex', + source=program_elf, + action='$OBJCOPY -O ihex $SOURCE $TARGET', +) + +program_pkg = env.Command( + target='ble_firmware.zip', + source=program_hex, + action=[ + f'python ../../pc-nrfutil/nordicsemi/ pkg generate --hw-version 52 --sd-req=0x100 --application $SOURCE --key-file ./embed/ble_bootloader/priv.pem $TARGET --application-version-string {tools.get_version("embed/ble_firmware/version.h")}' + ], +) + +softdevice_pkg = env.Command( + target='ble_softdevice.zip', + source=None, + action=[ + f'python ../../pc-nrfutil/nordicsemi/ pkg generate --hw-version 52 --sd-req=0x100 --key-file ./embed/ble_bootloader/priv.pem $TARGET --sd-id=0x100 --softdevice ./embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex' + ], +) + + +settings = env.Command( + target='settings.hex', + source=program_hex, + action=f'python ../../pc-nrfutil/nordicsemi/ settings generate --family NRF52 --application $SOURCE --application-version-string {tools.get_version("embed/ble_firmware/version.h")} --bootloader-version {tools.get_version_int("embed/ble_bootloader/version.h")} --softdevice ./embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --key-file ./embed/ble_bootloader/priv.pem $TARGET', +) + +program_merge = env.Command( + target='ble_firmware_merged.hex', + source=[program_hex, settings], + action='mergehex -m $SOURCES -o $TARGET', +) + +program_bin = env.Command( + target='ble_firmware.bin', + source=program_elf, + action=[ + '$OBJCOPY -O binary $SOURCE $TARGET', + '$CP $TARGET ' + BINARY_NAME, + ], +) + +env.Depends(program_bin, program_hex) +env.Depends(program_pkg, program_hex) +env.Depends(settings, program_hex) +env.Depends(program_bin, program_pkg) +env.Depends(program_bin, softdevice_pkg) +env.Depends(program_merge, settings) +env.Depends(program_merge, program_hex) +env.Depends(program_bin, program_merge) diff --git a/core/SConstruct b/core/SConstruct index a04364313..4ec232348 100644 --- a/core/SConstruct +++ b/core/SConstruct @@ -1,5 +1,7 @@ # pylint: disable=E0602 +SConscript('SConscript.ble_bootloader', variant_dir='build/ble_bootloader', duplicate=False) +SConscript('SConscript.ble_firmware', variant_dir='build/ble_firmware', duplicate=False) SConscript('SConscript.boardloader', variant_dir='build/boardloader', duplicate=False) SConscript('SConscript.bootloader', variant_dir='build/bootloader', duplicate=False) SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplicate=False) diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.options b/core/embed/ble_bootloader/dfu/dfu-cc.options new file mode 100644 index 000000000..de4fcdb86 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.options @@ -0,0 +1,5 @@ +dfu.Hash.hash max_size:32 +dfu.SignedCommand.signature max_size:64 +dfu.InitCommand.sd_req max_count:16 +dfu.InitCommand.boot_validation max_count:3 +dfu.BootValidation.bytes max_size:64 \ No newline at end of file diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.pb.c b/core/embed/ble_bootloader/dfu/dfu-cc.pb.c new file mode 100644 index 000000000..20a00e52b --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.pb.c @@ -0,0 +1,30 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.5 */ + +#include "dfu-cc.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(dfu_Hash, dfu_Hash, AUTO) + + +PB_BIND(dfu_BootValidation, dfu_BootValidation, AUTO) + + +PB_BIND(dfu_InitCommand, dfu_InitCommand, 2) + + +PB_BIND(dfu_Command, dfu_Command, 2) + + +PB_BIND(dfu_SignedCommand, dfu_SignedCommand, 2) + + +PB_BIND(dfu_Packet, dfu_Packet, 2) + + + + + + diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.pb.h b/core/embed/ble_bootloader/dfu/dfu-cc.pb.h new file mode 100644 index 000000000..0c1351f24 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.pb.h @@ -0,0 +1,228 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.5 */ + +#ifndef PB_DFU_DFU_CC_PB_H_INCLUDED +#define PB_DFU_DFU_CC_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _dfu_FwType { + dfu_FwType_APPLICATION = 0, + dfu_FwType_SOFTDEVICE = 1, + dfu_FwType_BOOTLOADER = 2, + dfu_FwType_SOFTDEVICE_BOOTLOADER = 3, + dfu_FwType_EXTERNAL_APPLICATION = 4 +} dfu_FwType; + +typedef enum _dfu_HashType { + dfu_HashType_NO_HASH = 0, + dfu_HashType_CRC = 1, + dfu_HashType_SHA128 = 2, + dfu_HashType_SHA256 = 3, + dfu_HashType_SHA512 = 4 +} dfu_HashType; + +typedef enum _dfu_OpCode { + dfu_OpCode_INIT = 1 +} dfu_OpCode; + +/* Struct definitions */ +typedef PB_BYTES_ARRAY_T(64) dfu_BootValidation_bytes_t; +typedef struct _dfu_BootValidation { + uint32_t sigmask; + dfu_BootValidation_bytes_t bytes; +} dfu_BootValidation; + +typedef PB_BYTES_ARRAY_T(32) dfu_Hash_hash_t; +typedef struct _dfu_Hash { + dfu_HashType hash_type; + dfu_Hash_hash_t hash; +} dfu_Hash; + +/* Commands data */ +typedef struct _dfu_InitCommand { + bool has_fw_version; + uint32_t fw_version; + bool has_hw_version; + uint32_t hw_version; + pb_size_t sd_req_count; + uint32_t sd_req[16]; + bool has_type; + dfu_FwType type; + bool has_sd_size; + uint32_t sd_size; + bool has_bl_size; + uint32_t bl_size; + bool has_app_size; + uint32_t app_size; + bool has_hash; + dfu_Hash hash; + bool has_is_debug; + bool is_debug; + pb_size_t boot_validation_count; + dfu_BootValidation boot_validation[3]; +} dfu_InitCommand; + +/* Command type */ +typedef struct _dfu_Command { + bool has_op_code; + dfu_OpCode op_code; + bool has_init; + dfu_InitCommand init; +} dfu_Command; + +typedef PB_BYTES_ARRAY_T(64) dfu_SignedCommand_signature_t; +typedef struct _dfu_SignedCommand { + dfu_Command command; + uint32_t sigmask; + dfu_SignedCommand_signature_t signature; +} dfu_SignedCommand; + +/* Parent packet type */ +typedef struct _dfu_Packet { + bool has_command; + dfu_Command command; + bool has_signed_command; + dfu_SignedCommand signed_command; +} dfu_Packet; + + +/* Helper constants for enums */ +#define _dfu_FwType_MIN dfu_FwType_APPLICATION +#define _dfu_FwType_MAX dfu_FwType_EXTERNAL_APPLICATION +#define _dfu_FwType_ARRAYSIZE ((dfu_FwType)(dfu_FwType_EXTERNAL_APPLICATION+1)) + +#define _dfu_HashType_MIN dfu_HashType_NO_HASH +#define _dfu_HashType_MAX dfu_HashType_SHA512 +#define _dfu_HashType_ARRAYSIZE ((dfu_HashType)(dfu_HashType_SHA512+1)) + +#define _dfu_OpCode_MIN dfu_OpCode_INIT +#define _dfu_OpCode_MAX dfu_OpCode_INIT +#define _dfu_OpCode_ARRAYSIZE ((dfu_OpCode)(dfu_OpCode_INIT+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define dfu_Hash_init_default {_dfu_HashType_MIN, {0, {0}}} +#define dfu_BootValidation_init_default {0, {0, {0}}} +#define dfu_InitCommand_init_default {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_default, false, false, 0, {dfu_BootValidation_init_default, dfu_BootValidation_init_default, dfu_BootValidation_init_default}} +#define dfu_Command_init_default {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_default} +#define dfu_SignedCommand_init_default {dfu_Command_init_default, 0, {0, {0}}} +#define dfu_Packet_init_default {false, dfu_Command_init_default, false, dfu_SignedCommand_init_default} +#define dfu_Hash_init_zero {_dfu_HashType_MIN, {0, {0}}} +#define dfu_BootValidation_init_zero {0, {0, {0}}} +#define dfu_InitCommand_init_zero {false, 0, false, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, false, _dfu_FwType_MIN, false, 0, false, 0, false, 0, false, dfu_Hash_init_zero, false, 0, 0, {dfu_BootValidation_init_zero, dfu_BootValidation_init_zero, dfu_BootValidation_init_zero}} +#define dfu_Command_init_zero {false, _dfu_OpCode_MIN, false, dfu_InitCommand_init_zero} +#define dfu_SignedCommand_init_zero {dfu_Command_init_zero, 0, {0, {0}}} +#define dfu_Packet_init_zero {false, dfu_Command_init_zero, false, dfu_SignedCommand_init_zero} + +/* Field tags (for use in manual encoding/decoding) */ +#define dfu_BootValidation_sigmask_tag 1 +#define dfu_BootValidation_bytes_tag 2 +#define dfu_Hash_hash_type_tag 1 +#define dfu_Hash_hash_tag 2 +#define dfu_InitCommand_fw_version_tag 1 +#define dfu_InitCommand_hw_version_tag 2 +#define dfu_InitCommand_sd_req_tag 3 +#define dfu_InitCommand_type_tag 4 +#define dfu_InitCommand_sd_size_tag 5 +#define dfu_InitCommand_bl_size_tag 6 +#define dfu_InitCommand_app_size_tag 7 +#define dfu_InitCommand_hash_tag 8 +#define dfu_InitCommand_is_debug_tag 9 +#define dfu_InitCommand_boot_validation_tag 10 +#define dfu_Command_op_code_tag 1 +#define dfu_Command_init_tag 2 +#define dfu_SignedCommand_command_tag 1 +#define dfu_SignedCommand_sigmask_tag 2 +#define dfu_SignedCommand_signature_tag 3 +#define dfu_Packet_command_tag 1 +#define dfu_Packet_signed_command_tag 2 + +/* Struct field encoding specification for nanopb */ +#define dfu_Hash_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, UENUM, hash_type, 1) \ +X(a, STATIC, REQUIRED, BYTES, hash, 2) +#define dfu_Hash_CALLBACK NULL +#define dfu_Hash_DEFAULT NULL + +#define dfu_BootValidation_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, UINT32, sigmask, 1) \ +X(a, STATIC, REQUIRED, BYTES, bytes, 2) +#define dfu_BootValidation_CALLBACK NULL +#define dfu_BootValidation_DEFAULT NULL + +#define dfu_InitCommand_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, UINT32, fw_version, 1) \ +X(a, STATIC, OPTIONAL, UINT32, hw_version, 2) \ +X(a, STATIC, REPEATED, UINT32, sd_req, 3) \ +X(a, STATIC, OPTIONAL, UENUM, type, 4) \ +X(a, STATIC, OPTIONAL, UINT32, sd_size, 5) \ +X(a, STATIC, OPTIONAL, UINT32, bl_size, 6) \ +X(a, STATIC, OPTIONAL, UINT32, app_size, 7) \ +X(a, STATIC, OPTIONAL, MESSAGE, hash, 8) \ +X(a, STATIC, OPTIONAL, BOOL, is_debug, 9) \ +X(a, STATIC, REPEATED, MESSAGE, boot_validation, 10) +#define dfu_InitCommand_CALLBACK NULL +#define dfu_InitCommand_DEFAULT (const pb_byte_t*)"\x48\x00\x00" +#define dfu_InitCommand_hash_MSGTYPE dfu_Hash +#define dfu_InitCommand_boot_validation_MSGTYPE dfu_BootValidation + +#define dfu_Command_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, UENUM, op_code, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, init, 2) +#define dfu_Command_CALLBACK NULL +#define dfu_Command_DEFAULT (const pb_byte_t*)"\x08\x01\x00" +#define dfu_Command_init_MSGTYPE dfu_InitCommand + +#define dfu_SignedCommand_FIELDLIST(X, a) \ +X(a, STATIC, REQUIRED, MESSAGE, command, 1) \ +X(a, STATIC, REQUIRED, UINT32, sigmask, 2) \ +X(a, STATIC, REQUIRED, BYTES, signature, 3) +#define dfu_SignedCommand_CALLBACK NULL +#define dfu_SignedCommand_DEFAULT NULL +#define dfu_SignedCommand_command_MSGTYPE dfu_Command + +#define dfu_Packet_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, command, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, signed_command, 2) +#define dfu_Packet_CALLBACK NULL +#define dfu_Packet_DEFAULT NULL +#define dfu_Packet_command_MSGTYPE dfu_Command +#define dfu_Packet_signed_command_MSGTYPE dfu_SignedCommand + +extern const pb_msgdesc_t dfu_Hash_msg; +extern const pb_msgdesc_t dfu_BootValidation_msg; +extern const pb_msgdesc_t dfu_InitCommand_msg; +extern const pb_msgdesc_t dfu_Command_msg; +extern const pb_msgdesc_t dfu_SignedCommand_msg; +extern const pb_msgdesc_t dfu_Packet_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define dfu_Hash_fields &dfu_Hash_msg +#define dfu_BootValidation_fields &dfu_BootValidation_msg +#define dfu_InitCommand_fields &dfu_InitCommand_msg +#define dfu_Command_fields &dfu_Command_msg +#define dfu_SignedCommand_fields &dfu_SignedCommand_msg +#define dfu_Packet_fields &dfu_Packet_msg + +/* Maximum encoded size of messages (where known) */ +#define dfu_BootValidation_size 72 +#define dfu_Command_size 395 +#define dfu_Hash_size 36 +#define dfu_InitCommand_size 390 +#define dfu_Packet_size 871 +#define dfu_SignedCommand_size 470 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/core/embed/ble_bootloader/dfu/dfu-cc.proto b/core/embed/ble_bootloader/dfu/dfu-cc.proto new file mode 100644 index 000000000..c31f3d915 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/dfu-cc.proto @@ -0,0 +1,69 @@ +package dfu; + +// Version 0.1 + +enum FwType { + APPLICATION = 0; + SOFTDEVICE = 1; + BOOTLOADER = 2; + SOFTDEVICE_BOOTLOADER = 3; + EXTERNAL_APPLICATION = 4; +} + +enum HashType { + NO_HASH = 0; + CRC = 1; + SHA128 = 2; + SHA256 = 3; + SHA512 = 4; +} + +enum OpCode { + INIT = 1; +} + +message Hash { + required HashType hash_type = 1; + required bytes hash = 2; +} + +message BootValidation { + + required uint32 sigmask = 1; + required bytes bytes = 2; +} + +// Commands data +message InitCommand { + optional uint32 fw_version = 1; + optional uint32 hw_version = 2; + repeated uint32 sd_req = 3 [packed = true]; + optional FwType type = 4; + + optional uint32 sd_size = 5; + optional uint32 bl_size = 6; + optional uint32 app_size = 7; + + optional Hash hash = 8; + + optional bool is_debug = 9 [default = false]; + repeated BootValidation boot_validation = 10; +} + +// Command type +message Command { + optional OpCode op_code = 1; + optional InitCommand init = 2; +} + +message SignedCommand { + required Command command = 1; + required uint32 sigmask = 2; + required bytes signature = 3; +} + +// Parent packet type +message Packet { + optional Command command = 1; + optional SignedCommand signed_command = 2; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu.c b/core/embed/ble_bootloader/dfu/nrf_dfu.c new file mode 100644 index 000000000..c03ad0b9f --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu.c @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu.h" + +#include "nrf_dfu_utils.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_log.h" + +static nrf_dfu_observer_t m_user_observer; // +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define NRF_DFU_SCHED_EVENT_DATA_SIZE (sizeof(nrf_dfu_request_t)) + + +/** @brief Function for initializing a DFU operation. + * + * This function initializes a DFU operation and any transports that are registered + * in the system. + * + * @param[in] observer Callback function for receiving DFU notifications. + * + * @retval NRF_SUCCESS If the DFU operation was successfully initialized. + */ +uint32_t nrf_dfu_init(nrf_dfu_observer_t observer); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c new file mode 100644 index 000000000..562249485 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.c @@ -0,0 +1,167 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#include "nrf_fstorage.h" +#include "nrf_fstorage_sd.h" +#include "nrf_fstorage_nvmc.h" + + +#define NRF_LOG_MODULE_NAME nrf_dfu_flash +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt); + + +NRF_FSTORAGE_DEF(nrf_fstorage_t m_fs) = +{ + .evt_handler = dfu_fstorage_evt_handler, + .start_addr = MBR_SIZE, + .end_addr = BOOTLOADER_SETTINGS_ADDRESS + BOOTLOADER_SETTINGS_PAGE_SIZE +}; + +static uint32_t m_flash_operations_pending; + +void dfu_fstorage_evt_handler(nrf_fstorage_evt_t * p_evt) +{ + if (NRF_LOG_ENABLED && (m_flash_operations_pending > 0)) + { + m_flash_operations_pending--; + } + + if (p_evt->result == NRF_SUCCESS) + { + NRF_LOG_DEBUG("Flash %s success: addr=%p, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->addr, m_flash_operations_pending); + } + else + { + NRF_LOG_DEBUG("Flash %s failed (0x%x): addr=%p, len=0x%x bytes, pending %d", + (p_evt->id == NRF_FSTORAGE_EVT_WRITE_RESULT) ? "write" : "erase", + p_evt->result, p_evt->addr, p_evt->len, m_flash_operations_pending); + } + + if (p_evt->p_param) + { + //lint -save -e611 (Suspicious cast) + ((nrf_dfu_flash_callback_t)(p_evt->p_param))((void*)p_evt->p_src); + //lint -restore + } +} + + +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized) +{ + nrf_fstorage_api_t * p_api_impl; + + /* Setup the desired API implementation. */ +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + if (sd_irq_initialized) + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_sd backend."); + p_api_impl = &nrf_fstorage_sd; + } + else +#endif + { + NRF_LOG_DEBUG("Initializing nrf_fstorage_nvmc backend."); + p_api_impl = &nrf_fstorage_nvmc; + } + + return nrf_fstorage_init(&m_fs, p_api_impl, NULL); +} + + +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_write(addr=%p, src=%p, len=%d bytes), queue usage: %d", + dest, p_src, len, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_write(&m_fs, dest, p_src, len, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_write() failed with error 0x%x.", rc); + } + + return rc; +} + + +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, + uint32_t num_pages, + nrf_dfu_flash_callback_t callback) +{ + ret_code_t rc; + + NRF_LOG_DEBUG("nrf_fstorage_erase(addr=0x%p, len=%d pages), queue usage: %d", + page_addr, num_pages, m_flash_operations_pending); + + //lint -save -e611 (Suspicious cast) + rc = nrf_fstorage_erase(&m_fs, page_addr, num_pages, (void *)callback); + //lint -restore + + if ((NRF_LOG_ENABLED) && (rc == NRF_SUCCESS)) + { + m_flash_operations_pending++; + } + else + { + NRF_LOG_WARNING("nrf_fstorage_erase() failed with error 0x%x.", rc); + } + + return rc; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h new file mode 100644 index 000000000..79d7dec1e --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_flash.h @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_flash Flash operations + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_FLASH_H__ +#define NRF_DFU_FLASH_H__ + +#include +#include +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief nrf_fstorage event handler function for DFU fstorage operations. + * + * This function will be called after a flash operation has completed. + */ +typedef void (*nrf_dfu_flash_callback_t)(void * p_buf); + + +/**@brief Function for initializing the flash module. + * + * Depending on whether or not the SoftDevice is present and its IRQ have been initialized, + * this function initializes the correct @ref nrf_fstorage backend. + * + * @param[in] sd_irq_initialized Whether or not the SoftDevice IRQ have been initialized. + * + * @retval NRF_SUCCESS If the operation was successful. + */ +ret_code_t nrf_dfu_flash_init(bool sd_irq_initialized); + + +/**@brief Function for storing data to flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @note The content of @p p_src should be kept in memory until the operation has completed. + * + * @param[in] dest The address where the data should be stored. + * @param[in] p_src Pointer to the address where the data should be copied from. + * This address can be in flash or RAM. + * @param[in] len The number of bytes to be copied from @p p_src to @p dest. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p p_src or @p dest is not word-aligned. + * @retval NRF_ERROR_INVALID_LENGTH If @p len is zero. + * @retval NRF_ERROR_NULL If @p p_src is NULL. + * @retval NRF_ERROR_NO_MEM If nrf_fstorage is out of memory. + */ +ret_code_t nrf_dfu_flash_store(uint32_t dest, + void const * p_src, + uint32_t len, + nrf_dfu_flash_callback_t callback); + + +/**@brief Function for erasing data from flash. + * + * This functions is asynchronous when the SoftDevice is enabled and synchronous when + * the SoftDevice is not present or disabled. In both cases, if a callback function is provided, + * it will be called when the operation has completed. + * + * @param[in] page_addr The address of the first flash page to be deleted. + * @param[in] num_pages The number of flash pages to be deleted. + * @param[in] callback Callback function. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INVALID_STATE If nrf_dfu_flash is not initialized. + * @retval NRF_ERROR_INVALID_ADDR If @p page_addr is not aligned to a page boundary or the + * operation would go beyond the flash memory boundaries. + * @retval NRF_ERROR_INVALID_LENGTH If @p num_pages is zero. + * @retval NRF_ERROR_NULL If @p page_addr is NULL. + * @retval NRF_ERROR_NO_MEM If the queue of nrf_fstorage is full. + */ +ret_code_t nrf_dfu_flash_erase(uint32_t page_addr, uint32_t num_pages, nrf_dfu_flash_callback_t callback); + + +#ifdef __cplusplus +} +#endif + + +#endif // NRF_DFU_FLASH_H__ +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c new file mode 100644 index 000000000..3103f591c --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.c @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_handling_error.h" + +#include "nrf_log.h" +#include "nrf_dfu_req_handler.h" + +static nrf_dfu_ext_error_code_t m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code) +{ + m_last_error = error_code; + + return NRF_DFU_RES_CODE_EXT_ERROR; +} + +nrf_dfu_ext_error_code_t ext_error_get() +{ + nrf_dfu_ext_error_code_t last_error = m_last_error; + m_last_error = NRF_DFU_EXT_ERROR_NO_ERROR; + + return last_error; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h new file mode 100644 index 000000000..5249d3961 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_handling_error.h @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + /**@file + * + * @defgroup nrf_dfu_rescodes DFU result codes + * @{ + * @ingroup sdk_nrf_dfu_transport + * @brief When the DFU controller sends requests to the DFU bootloader on + * the DFU target, the DFU bootloader answers with any of these result codes. + */ + + +#ifndef DFU_HANDLING_ERROR_H__ +#define DFU_HANDLING_ERROR_H__ + +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +/**@brief DFU request extended result codes. + * + * @details When an event returns @ref NRF_DFU_RES_CODE_EXT_ERROR, it also stores an extended error code. + * The transport layer can then send the extended error code together with the error code to give + * the controller additional information about the cause of the error. + */ +typedef enum +{ + NRF_DFU_EXT_ERROR_NO_ERROR = 0x00, /**< No extended error code has been set. This error indicates an implementation problem. */ + NRF_DFU_EXT_ERROR_INVALID_ERROR_CODE = 0x01, /**< Invalid error code. This error code should never be used outside of development. */ + NRF_DFU_EXT_ERROR_WRONG_COMMAND_FORMAT = 0x02, /**< The format of the command was incorrect. This error code is not used in the + current implementation, because @ref NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED + and @ref NRF_DFU_RES_CODE_INVALID_PARAMETER cover all + possible format errors. */ + NRF_DFU_EXT_ERROR_UNKNOWN_COMMAND = 0x03, /**< The command was successfully parsed, but it is not supported or unknown. */ + NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID = 0x04, /**< The init command is invalid. The init packet either has + an invalid update type or it is missing required fields for the update type + (for example, the init packet for a SoftDevice update is missing the SoftDevice size field). */ + NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE = 0x05, /**< The firmware version is too low. For an application or SoftDevice, the version must be greater than + or equal to the current version. For a bootloader, it must be greater than the current version. + to the current version. This requirement prevents downgrade attacks.*/ + NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE = 0x06, /**< The hardware version of the device does not match the required + hardware version for the update. */ + NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE = 0x07, /**< The array of supported SoftDevices for the update does not contain + the FWID of the current SoftDevice or the first FWID is '0' on a + bootloader which requires the SoftDevice to be present. */ + NRF_DFU_EXT_ERROR_SIGNATURE_MISSING = 0x08, /**< The init packet does not contain a signature. This error code is not used in the + current implementation, because init packets without a signature + are regarded as invalid. */ + NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE = 0x09, /**< The hash type that is specified by the init packet is not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_HASH_FAILED = 0x0A, /**< The hash of the firmware image cannot be calculated. */ + NRF_DFU_EXT_ERROR_WRONG_SIGNATURE_TYPE = 0x0B, /**< The type of the signature is unknown or not supported by the DFU bootloader. */ + NRF_DFU_EXT_ERROR_VERIFICATION_FAILED = 0x0C, /**< The hash of the received firmware image does not match the hash in the init packet. */ + NRF_DFU_EXT_ERROR_INSUFFICIENT_SPACE = 0x0D, /**< The available space on the device is insufficient to hold the firmware. */ +} nrf_dfu_ext_error_code_t; + + +/**@brief Function for setting an extended error code that can be retrieved later. + * + * @details When an extended error occurs in the DFU process, this function can be used to store the error. + * + * @param error_code The error code to store. + * + * @retval NRF_DFU_RES_CODE_EXT_ERROR + */ +nrf_dfu_result_t ext_error_set(nrf_dfu_ext_error_code_t error_code); + +/**@brief Function for getting the most recent extended error code. + * + * @details This function is used by the transport layer to fetch the most recent extended error code. + * + * @return The most recent error code. If the function is called again before a new error occurs, @ref NRF_DFU_EXT_ERROR_NO_ERROR is returned. + */ +nrf_dfu_ext_error_code_t ext_error_get( void ); + + +#ifdef __cplusplus +} +#endif + +#endif // DFU_HANDLING_ERROR_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c new file mode 100644 index 000000000..3644ca3e0 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.c @@ -0,0 +1,105 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_mbr.h" +#include "nrf_mbr.h" +#include "nrf_dfu_types.h" +#include "nrf_log.h" +#include "nrf_bootloader_info.h" + +#define MBR_IRQ_FORWARD_ADDRESS_ADDRESS (0x20000000) //!< The address of the variable that decides where the MBR forwards interrupts + +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len) +{ + uint32_t ret_val; + uint32_t const len_words = len / sizeof(uint32_t); + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_COPY_BL, + .params.copy_bl.bl_src = p_src, + .params.copy_bl.bl_len = len_words + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_init_sd(void) +{ + uint32_t ret_val; + + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_INIT_SD + }; + + ret_val = sd_mbr_command(&command); + + return ret_val; +} + + +uint32_t nrf_dfu_mbr_irq_forward_address_set(void) +{ + uint32_t ret_val = NRF_ERROR_INVALID_PARAM; + uint32_t address = MBR_SIZE; + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + sd_mbr_command_t command = + { + .command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, + .params.irq_forward_address_set.address = address, + }; + + ret_val = sd_mbr_command(&command); +#endif + + if (ret_val == NRF_ERROR_INVALID_PARAM) + { + // Manually set the forward address if this MBR doesn't have the command. + *(uint32_t *)(MBR_IRQ_FORWARD_ADDRESS_ADDRESS) = address; + + ret_val = NRF_SUCCESS; + } + + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h new file mode 100644 index 000000000..ac7208895 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_mbr.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_mbr MBR functions + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_MBR_H__ +#define NRF_DFU_MBR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Function for copying the bootloader using an MBR command. + * + * @param[in] p_src Source address of the bootloader data to copy. + * @param[in] len Length of the data to copy in bytes. + * + * @return This function will return only if the command request could not be run. + * See @ref sd_mbr_command_copy_bl_t for possible return values. + */ +uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len); + + +/** @brief Function for initializing the SoftDevice using an MBR command. + * + * @retval NRF_SUCCESS If the SoftDevice was initialized successfully. + * Any other return value indicates that the SoftDevice + * could not be initialized. + */ +uint32_t nrf_dfu_mbr_init_sd(void); + + +/** @brief Function for setting the address of the IRQ table to the app's using an MBR command. + * + * @retval NRF_SUCCESS If the address of the new irq table was set. Any other + * return value indicates that the address could not be set. + */ +uint32_t nrf_dfu_mbr_irq_forward_address_set(void); + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_MBR_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c new file mode 100644 index 000000000..1124369b6 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.c @@ -0,0 +1,864 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include +#include "sdk_config.h" +#include "nrf_dfu.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_req_handler.h" +#include "nrf_dfu_handling_error.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_fstorage.h" +#include "nrf_bootloader_info.h" +#include "app_util.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "app_scheduler.h" +#include "sdk_macros.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_req_handler +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define NRF_DFU_PROTOCOL_VERSION (0x01) + +#ifndef NRF_DFU_PROTOCOL_REDUCED +#define NRF_DFU_PROTOCOL_REDUCED 0 +#endif + +STATIC_ASSERT(dfu_SignedCommand_size <= INIT_COMMAND_MAX_SIZE); + +static uint32_t m_firmware_start_addr; /**< Start address of the current firmware image. */ +static uint32_t m_firmware_size_req; /**< The size of the entire firmware image. Defined by the init command. */ + +static nrf_dfu_observer_t m_observer; + + +static void on_dfu_complete(nrf_fstorage_evt_t * p_evt) +{ + UNUSED_PARAMETER(p_evt); + + NRF_LOG_DEBUG("All flash operations have completed. DFU completed."); + + m_observer(NRF_DFU_EVT_DFU_COMPLETED); +} + + +static nrf_dfu_result_t ext_err_code_handle(nrf_dfu_result_t ret_val) +{ + if (ret_val < NRF_DFU_RES_CODE_EXT_ERROR) + { + return ret_val; + } + else + { + nrf_dfu_ext_error_code_t ext_err = + (nrf_dfu_ext_error_code_t)((uint8_t)ret_val - (uint8_t)NRF_DFU_RES_CODE_EXT_ERROR); + return ext_error_set(ext_err); + } +} + + +#if !NRF_DFU_PROTOCOL_REDUCED +static void on_protocol_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PROTOCOL_VERSION"); + + if (NRF_DFU_PROTOCOL_VERSION_MSG) + { + p_res->protocol.version = NRF_DFU_PROTOCOL_VERSION; + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_PROTOCOL_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + } +} + + +static void on_hw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_HARDWARE_VERSION"); + + p_res->hardware.part = NRF_FICR->INFO.PART; + p_res->hardware.variant = NRF_FICR->INFO.VARIANT; + + /* FICR values are in Kilobytes, we report them in bytes. */ + p_res->hardware.memory.ram_size = NRF_FICR->INFO.RAM * 1024; + p_res->hardware.memory.rom_size = NRF_FICR->INFO.FLASH * 1024; + p_res->hardware.memory.rom_page_size = NRF_FICR->CODEPAGESIZE; +} + + +static void on_fw_version_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_FIRMWARE_VERSION"); + NRF_LOG_DEBUG("Firmware image requested: %d", p_req->firmware.image_number); + + if (NRF_DFU_PROTOCOL_FW_VERSION_MSG) + { + uint8_t fw_count = 1; + + if (SD_PRESENT) + { + fw_count++; + } + + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + fw_count++; + } + + p_res->result = NRF_DFU_RES_CODE_SUCCESS; + + if (p_req->firmware.image_number == 0) + { + /* Bootloader is always present and it is always image zero. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_BOOTLOADER; + p_res->firmware.version = s_dfu_settings.bootloader_version; + p_res->firmware.addr = BOOTLOADER_START_ADDR; + p_res->firmware.len = BOOTLOADER_SIZE; + } + else if ((p_req->firmware.image_number == 1) && SD_PRESENT) + { + /* If a SoftDevice is present, it will be firmware image one. */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE; + p_res->firmware.version = SD_VERSION_GET(MBR_SIZE); + p_res->firmware.addr = MBR_SIZE; + p_res->firmware.len = SD_SIZE_GET(MBR_SIZE); + } + else if ((p_req->firmware.image_number < fw_count)) + { + /* Either there is no SoftDevice and the firmware image requested is one, + * or there is a SoftDevice and the firmware image requested is two. + */ + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_APPLICATION; + p_res->firmware.version = s_dfu_settings.app_version; + p_res->firmware.addr = nrf_dfu_app_start_address(); + p_res->firmware.len = s_dfu_settings.bank_0.image_size; + } + else + { + NRF_LOG_DEBUG("No such firmware image"); + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + p_res->firmware.version = 0x00; + p_res->firmware.addr = 0x00; + p_res->firmware.len = 0x00; + } + } + else + { + NRF_LOG_DEBUG("NRF_DFU_OP_FIRMWARE_VERSION disabled."); + p_res->result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + p_res->firmware.type = NRF_DFU_FIRMWARE_TYPE_UNKNOWN; + } +} + + +static void on_ping_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_PING"); + p_res->ping.id = p_req->ping.id; +} + + +static void on_mtu_get_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_MTU_GET"); + p_res->mtu.size = p_req->mtu.size; +} +#endif // !NRF_DFU_PROTOCOL_REDUCED + + +static void on_prn_set_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_RECEIPT_NOTIF_SET"); +} + + +static void on_abort_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + UNUSED_PARAMETER(p_res); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_ABORT"); + + m_observer(NRF_DFU_EVT_DFU_ABORTED); +} + + +/* Set offset and CRC fields in the response for a 'command' message. */ +static void cmd_response_offset_and_crc_set(nrf_dfu_response_t * const p_res) +{ + ASSERT(p_res); + + /* Copy the CRC and offset of the init packet. */ + p_res->crc.offset = s_dfu_settings.progress.command_offset; + p_res->crc.crc = s_dfu_settings.progress.command_crc; +} + + +static void on_cmd_obj_select_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (command)"); + + p_res->select.max_size = INIT_COMMAND_MAX_SIZE; + cmd_response_offset_and_crc_set(p_res); +} + + +static void on_cmd_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (command)"); + + m_observer(NRF_DFU_EVT_DFU_STARTED); + + nrf_dfu_result_t ret_val = nrf_dfu_validation_init_cmd_create(p_req->create.object_size); + p_res->result = ext_err_code_handle(ret_val); +} + + +static void on_cmd_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_req->write.p_data); + ASSERT(p_req->write.len); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (command)"); + + nrf_dfu_result_t ret_val; + + ret_val = nrf_dfu_validation_init_cmd_append(p_req->write.p_data, p_req->write.len); + p_res->result = ext_err_code_handle(ret_val); + + /* Update response. This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. */ + cmd_response_offset_and_crc_set(p_res); + + /* If a callback to free the request payload buffer was provided, invoke it now. */ + if (p_req->callback.write) + { + p_req->callback.write((void*)p_req->write.p_data); + } +} + + +static void on_cmd_obj_execute_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (command)"); + + nrf_dfu_result_t ret_val; + ret_val = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + p_res->result = ext_err_code_handle(ret_val); + + if (p_res->result == NRF_DFU_RES_CODE_SUCCESS) + { + if (nrf_dfu_settings_write_and_backup(NULL) == NRF_SUCCESS) + { + /* Setting DFU to initialized */ + NRF_LOG_DEBUG("Writing valid init command to flash."); + } + else + { + p_res->result = NRF_DFU_RES_CODE_OPERATION_FAILED; + } + } +} + + +static void on_cmd_obj_crc_request(nrf_dfu_request_t const * p_req, nrf_dfu_response_t * p_res) +{ + UNUSED_PARAMETER(p_req); + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (command)"); + + cmd_response_offset_and_crc_set(p_res); +} + + +/** @brief Function handling command requests from the transport layer. + * + * @param p_req[in] Pointer to the structure holding the DFU request. + * @param p_res[out] Pointer to the structure holding the DFU response. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * Any other error code indicates that the data request + * could not be handled. + */ +static void nrf_dfu_command_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_cmd_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_cmd_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_cmd_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + on_cmd_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_cmd_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } +} + + +static void on_data_obj_select_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_SELECT (data)"); + + p_res->select.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->select.offset = s_dfu_settings.progress.firmware_image_offset; + + p_res->select.max_size = DATA_OBJECT_MAX_SIZE; + + NRF_LOG_DEBUG("crc = 0x%x, offset = 0x%x, max_size = 0x%x", + p_res->select.crc, + p_res->select.offset, + p_res->select.max_size); +} + + +static void on_data_obj_create_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_CREATE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + NRF_LOG_ERROR("Cannot create data object without valid init command"); + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + if (p_req->create.object_size == 0) + { + NRF_LOG_ERROR("Object size cannot be 0.") + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if ( ((p_req->create.object_size & (CODE_PAGE_SIZE - 1)) != 0) + && (s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size != m_firmware_size_req)) + { + NRF_LOG_ERROR("Object size must be page aligned"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + if (p_req->create.object_size > DATA_OBJECT_MAX_SIZE) + { + /* It is impossible to handle the command because the size is too large */ + NRF_LOG_ERROR("Invalid size for object (too large)"); + p_res->result = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + return; + } + + if ((s_dfu_settings.progress.firmware_image_offset_last + p_req->create.object_size) > + m_firmware_size_req) + { + NRF_LOG_ERROR("Creating the object with size 0x%08x would overflow firmware size. " + "Offset is 0x%08x and firmware size is 0x%08x.", + p_req->create.object_size, + s_dfu_settings.progress.firmware_image_offset_last, + m_firmware_size_req); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + s_dfu_settings.progress.data_object_size = p_req->create.object_size; + s_dfu_settings.progress.firmware_image_crc = s_dfu_settings.progress.firmware_image_crc_last; + s_dfu_settings.progress.firmware_image_offset = s_dfu_settings.progress.firmware_image_offset_last; + s_dfu_settings.write_offset = s_dfu_settings.progress.firmware_image_offset_last; + + /* Erase the page we're at. */ + if (nrf_dfu_flash_erase((m_firmware_start_addr + s_dfu_settings.progress.firmware_image_offset), + CEIL_DIV(p_req->create.object_size, CODE_PAGE_SIZE), NULL) != NRF_SUCCESS) + { + NRF_LOG_ERROR("Erase operation failed"); + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + return; + } + + NRF_LOG_DEBUG("Creating object with size: %d. Offset: 0x%08x, CRC: 0x%08x", + s_dfu_settings.progress.data_object_size, + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); +} + + +static void on_data_obj_write_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_WRITE (data)"); + + if (!nrf_dfu_validation_init_cmd_present()) + { + /* Can't accept data because DFU isn't initialized by init command. */ + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return; + } + + uint32_t const data_object_offset = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if ((p_req->write.len + data_object_offset) > s_dfu_settings.progress.data_object_size) + { + /* Can't accept data because too much data has been received. */ + NRF_LOG_ERROR("Write request too long"); + p_res->result = NRF_DFU_RES_CODE_INVALID_PARAMETER; + return; + } + + uint32_t const write_addr = m_firmware_start_addr + s_dfu_settings.write_offset; + /* CRC must be calculated before handing off the data to fstorage because the data is + * freed on write completion. + */ + uint32_t const next_crc = + crc32_compute(p_req->write.p_data, p_req->write.len, &s_dfu_settings.progress.firmware_image_crc); + + ASSERT(p_req->callback.write); + + ret_code_t ret = + nrf_dfu_flash_store(write_addr, p_req->write.p_data, p_req->write.len, p_req->callback.write); + + if (ret != NRF_SUCCESS) + { + /* When nrf_dfu_flash_store() fails because there is no space in the queue, + * stop processing the request so that the peer can detect a CRC error + * and retransmit this object. Remember to manually free the buffer ! + */ + p_req->callback.write((void*)p_req->write.p_data); + return; + } + + /* Update the CRC of the firmware image. */ + s_dfu_settings.write_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_offset += p_req->write.len; + s_dfu_settings.progress.firmware_image_crc = next_crc; + + /* This is only used when the PRN is triggered and the 'write' message + * is answered with a CRC message and these field are copied into the response. + */ + p_res->write.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->write.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_crc_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_CRC_GET (data)"); + NRF_LOG_DEBUG("Offset:%d, CRC:0x%08x", + s_dfu_settings.progress.firmware_image_offset, + s_dfu_settings.progress.firmware_image_crc); + + p_res->crc.crc = s_dfu_settings.progress.firmware_image_crc; + p_res->crc.offset = s_dfu_settings.progress.firmware_image_offset; +} + + +static void on_data_obj_execute_request_sched(void * p_evt, uint16_t event_length) +{ + UNUSED_PARAMETER(event_length); + + ret_code_t ret; + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + + /* Wait for all buffers to be written in flash. */ + if (nrf_fstorage_is_busy(NULL)) + { + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), on_data_obj_execute_request_sched); + if (ret != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed to schedule object execute: 0x%x.", ret); + } + return; + } + + nrf_dfu_response_t res = + { + .request = NRF_DFU_OP_OBJECT_EXECUTE, + }; + + if (s_dfu_settings.progress.firmware_image_offset == m_firmware_size_req) + { + NRF_LOG_DEBUG("Whole firmware image received. Postvalidating."); + + #if NRF_DFU_IN_APP + res.result = nrf_dfu_validation_post_data_execute(m_firmware_start_addr, m_firmware_size_req); + #else + res.result = nrf_dfu_validation_activation_prepare(m_firmware_start_addr, m_firmware_size_req); + #endif + + res.result = ext_err_code_handle(res.result); + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + ret = nrf_dfu_settings_write_and_backup((nrf_dfu_flash_callback_t)on_dfu_complete); + UNUSED_RETURN_VALUE(ret); + } + else + { + res.result = NRF_DFU_RES_CODE_SUCCESS; + + /* Provide response to transport */ + p_req->callback.response(&res, p_req->p_context); + + if (NRF_DFU_SAVE_PROGRESS_IN_FLASH) + { + /* Allowing skipping settings backup to save time and flash wear. */ + ret = nrf_dfu_settings_write_and_backup(NULL); + UNUSED_RETURN_VALUE(ret); + } + } + + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", res.result); +} + + +static bool on_data_obj_execute_request(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + NRF_LOG_DEBUG("Handle NRF_DFU_OP_OBJECT_EXECUTE (data)"); + + uint32_t const data_object_size = s_dfu_settings.progress.firmware_image_offset - + s_dfu_settings.progress.firmware_image_offset_last; + + if (s_dfu_settings.progress.data_object_size != data_object_size) + { + /* The size of the written object was not as expected. */ + NRF_LOG_ERROR("Invalid data. expected: %d, got: %d", + s_dfu_settings.progress.data_object_size, + data_object_size); + + p_res->result = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + return true; + } + + /* Update the offset and crc values for the last object written. */ + s_dfu_settings.progress.data_object_size = 0; + s_dfu_settings.progress.firmware_image_crc_last = s_dfu_settings.progress.firmware_image_crc; + s_dfu_settings.progress.firmware_image_offset_last = s_dfu_settings.progress.firmware_image_offset; + + on_data_obj_execute_request_sched(p_req, 0); + + m_observer(NRF_DFU_EVT_OBJECT_RECEIVED); + + return false; +} + + +static bool nrf_dfu_data_req(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + ASSERT(p_req); + ASSERT(p_res); + + bool response_ready = true; + + switch (p_req->request) + { + case NRF_DFU_OP_OBJECT_CREATE: + { + on_data_obj_create_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_WRITE: + { + on_data_obj_write_request(p_req, p_res); + } break; + + case NRF_DFU_OP_CRC_GET: + { + on_data_obj_crc_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_EXECUTE: + { + response_ready = on_data_obj_execute_request(p_req, p_res); + } break; + + case NRF_DFU_OP_OBJECT_SELECT: + { + on_data_obj_select_request(p_req, p_res); + } break; + + default: + { + ASSERT(false); + } break; + } + + return response_ready; +} + + +/**@brief Function for handling requests to manipulate data or command objects. + * + * @param[in] p_req Request. + * @param[out] p_res Response. + * + * @return Whether response is ready to be sent. + */ +static bool nrf_dfu_obj_op(nrf_dfu_request_t * p_req, nrf_dfu_response_t * p_res) +{ + /* Keep track of the current object type since write and execute requests don't contain it. */ + static nrf_dfu_obj_type_t current_object = NRF_DFU_OBJ_TYPE_COMMAND; + + if ( (p_req->request == NRF_DFU_OP_OBJECT_SELECT) + || (p_req->request == NRF_DFU_OP_OBJECT_CREATE)) + { + STATIC_ASSERT(offsetof(nrf_dfu_request_select_t, object_type) == + offsetof(nrf_dfu_request_create_t, object_type), + "Wrong object_type offset!"); + + current_object = (nrf_dfu_obj_type_t)(p_req->select.object_type); + } + + bool response_ready = true; + + switch (current_object) + { + case NRF_DFU_OBJ_TYPE_COMMAND: + nrf_dfu_command_req(p_req, p_res); + break; + + case NRF_DFU_OBJ_TYPE_DATA: + response_ready = nrf_dfu_data_req(p_req, p_res); + break; + + default: + /* The select request had an invalid object type. */ + NRF_LOG_ERROR("Invalid object type in request."); + current_object = NRF_DFU_OBJ_TYPE_INVALID; + p_res->result = NRF_DFU_RES_CODE_INVALID_OBJECT; + break; + } + + return response_ready; +} + + +static void nrf_dfu_req_handler_req_process(nrf_dfu_request_t * p_req) +{ + ASSERT(p_req->callback.response); + + bool response_ready = true; + + /* The request handlers assume these values to be set. */ + nrf_dfu_response_t response = + { + .request = p_req->request, + .result = NRF_DFU_RES_CODE_SUCCESS, + }; + + + switch (p_req->request) + { +#if !NRF_DFU_PROTOCOL_REDUCED + case NRF_DFU_OP_PROTOCOL_VERSION: + { + on_protocol_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_HARDWARE_VERSION: + { + on_hw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_FIRMWARE_VERSION: + { + on_fw_version_request(p_req, &response); + } break; + + case NRF_DFU_OP_PING: + { + on_ping_request(p_req, &response); + } break; + + case NRF_DFU_OP_MTU_GET: + { + on_mtu_get_request(p_req, &response); + } break; +#endif + case NRF_DFU_OP_RECEIPT_NOTIF_SET: + { + on_prn_set_request(p_req, &response); + } break; + + case NRF_DFU_OP_ABORT: + { + on_abort_request(p_req, &response); + } break; + + case NRF_DFU_OP_OBJECT_CREATE: + /* Restart the inactivity timer on CREATE messages. */ + /* Fallthrough. */ + case NRF_DFU_OP_OBJECT_SELECT: + case NRF_DFU_OP_OBJECT_WRITE: + case NRF_DFU_OP_OBJECT_EXECUTE: + case NRF_DFU_OP_CRC_GET: + { + response_ready = nrf_dfu_obj_op(p_req, &response); + } break; + + default: + NRF_LOG_INFO("Invalid opcode received: 0x%x.", p_req->request); + response.result = NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED; + break; + } + + if (response_ready) + { + NRF_LOG_DEBUG("Request handling complete. Result: 0x%x", response.result); + + p_req->callback.response(&response, p_req->p_context); + + if (response.result != NRF_DFU_RES_CODE_SUCCESS) + { + m_observer(NRF_DFU_EVT_DFU_FAILED); + } + } +} + + +static void nrf_dfu_req_handler_req(void * p_evt, uint16_t event_length) +{ + nrf_dfu_request_t * p_req = (nrf_dfu_request_t *)(p_evt); + nrf_dfu_req_handler_req_process(p_req); +} + + +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req) +{ + ret_code_t ret; + + if (p_req->callback.response == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + + ret = app_sched_event_put(p_req, sizeof(nrf_dfu_request_t), nrf_dfu_req_handler_req); + if (ret != NRF_SUCCESS) + { + NRF_LOG_WARNING("Scheduler ran out of space!"); + } + + return ret; +} + + +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer) +{ + ret_code_t ret_val; + nrf_dfu_result_t result; + + if (observer == NULL) + { + return NRF_ERROR_INVALID_PARAM; + } + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + ret_val = nrf_dfu_flash_init(true); +#else + ret_val = nrf_dfu_flash_init(false); +#endif + if (ret_val != NRF_SUCCESS) + { + return ret_val; + } + + nrf_dfu_validation_init(); + if (nrf_dfu_validation_init_cmd_present()) + { + /* Execute a previously received init packed. Subsequent executes will have no effect. */ + result = nrf_dfu_validation_init_cmd_execute(&m_firmware_start_addr, &m_firmware_size_req); + if (result != NRF_DFU_RES_CODE_SUCCESS) + { + /* Init packet in flash is not valid! */ + return NRF_ERROR_INTERNAL; + } + } + + m_observer = observer; + + /* Initialize extended error handling with "No error" as the most recent error. */ + result = ext_error_set(NRF_DFU_EXT_ERROR_NO_ERROR); + UNUSED_RETURN_VALUE(result); + + return NRF_SUCCESS; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h new file mode 100644 index 000000000..e9eb5c4f4 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_req_handler.h @@ -0,0 +1,346 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_req_handler Request handling + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_REQ_HANDLER_H__ +#define NRF_DFU_REQ_HANDLER_H__ + +#include +#include +#include "app_util_platform.h" +#include "nrf_dfu_flash.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +ANON_UNIONS_ENABLE; + +/** + * @brief DFU object types. + */ +typedef enum +{ + NRF_DFU_OBJ_TYPE_INVALID, //!< Invalid object type. + NRF_DFU_OBJ_TYPE_COMMAND, //!< Command object. + NRF_DFU_OBJ_TYPE_DATA, //!< Data object. +} nrf_dfu_obj_type_t; + +/** + * @brief DFU protocol operation. + */ +typedef enum +{ + NRF_DFU_OP_PROTOCOL_VERSION = 0x00, //!< Retrieve protocol version. + NRF_DFU_OP_OBJECT_CREATE = 0x01, //!< Create selected object. + NRF_DFU_OP_RECEIPT_NOTIF_SET = 0x02, //!< Set receipt notification. + NRF_DFU_OP_CRC_GET = 0x03, //!< Request CRC of selected object. + NRF_DFU_OP_OBJECT_EXECUTE = 0x04, //!< Execute selected object. + NRF_DFU_OP_OBJECT_SELECT = 0x06, //!< Select object. + NRF_DFU_OP_MTU_GET = 0x07, //!< Retrieve MTU size. + NRF_DFU_OP_OBJECT_WRITE = 0x08, //!< Write selected object. + NRF_DFU_OP_PING = 0x09, //!< Ping. + NRF_DFU_OP_HARDWARE_VERSION = 0x0A, //!< Retrieve hardware version. + NRF_DFU_OP_FIRMWARE_VERSION = 0x0B, //!< Retrieve firmware version. + NRF_DFU_OP_ABORT = 0x0C, //!< Abort the DFU procedure. + NRF_DFU_OP_RESPONSE = 0x60, //!< Response. + NRF_DFU_OP_INVALID = 0xFF, +} nrf_dfu_op_t; + +/** + * @brief DFU operation result code. + */ +typedef enum +{ + NRF_DFU_RES_CODE_INVALID = 0x00, //!< Invalid opcode. + NRF_DFU_RES_CODE_SUCCESS = 0x01, //!< Operation successful. + NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED = 0x02, //!< Opcode not supported. + NRF_DFU_RES_CODE_INVALID_PARAMETER = 0x03, //!< Missing or invalid parameter value. + NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES = 0x04, //!< Not enough memory for the data object. + NRF_DFU_RES_CODE_INVALID_OBJECT = 0x05, //!< Data object does not match the firmware and hardware requirements, the signature is wrong, or parsing the command failed. + NRF_DFU_RES_CODE_UNSUPPORTED_TYPE = 0x07, //!< Not a valid object type for a Create request. + NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED = 0x08, //!< The state of the DFU process does not allow this operation. + NRF_DFU_RES_CODE_OPERATION_FAILED = 0x0A, //!< Operation failed. + NRF_DFU_RES_CODE_EXT_ERROR = 0x0B, //!< Extended error. The next byte of the response contains the error code of the extended error (see @ref nrf_dfu_ext_error_code_t. + NRF_DFU_ERROR_INVALID_SIGNATURE = 0x0C, //!< The provided signature is wrong. +} nrf_dfu_result_t; + +typedef enum +{ + NRF_DFU_FIRMWARE_TYPE_SOFTDEVICE = 0x00, + NRF_DFU_FIRMWARE_TYPE_APPLICATION = 0x01, + NRF_DFU_FIRMWARE_TYPE_BOOTLOADER = 0x02, + NRF_DFU_FIRMWARE_TYPE_UNKNOWN = 0xFF, +} nrf_dfu_firmware_type_t; + +/** + * @brief @ref NRF_DFU_OP_PROTOCOL_VERSION response details. + */ +typedef struct +{ + uint8_t version; //!< Protocol version. +} nrf_dfu_response_protocol_t; + +/** + * @brief @ref NRF_DFU_OP_HARDWARE_VERSION response details. + */ +typedef struct +{ + uint32_t part; //!< Hardware part, from FICR register. + uint32_t variant; //!< Hardware variant, from FICR register. + struct + { + uint32_t rom_size; //!< ROM size, in bytes. + uint32_t ram_size; //!< RAM size, in bytes. + uint32_t rom_page_size; //!< ROM flash page size, in bytes. + } memory; +} nrf_dfu_response_hardware_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION response details. + */ +typedef struct +{ + nrf_dfu_firmware_type_t type; //!< Firmware type. + uint32_t version; //!< Firmware version. + uint32_t addr; //!< Firmware address in flash. + uint32_t len; //!< Firmware length in bytes. +} nrf_dfu_response_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. + uint32_t max_size; //!< Maximum size of selected object. +} nrf_dfu_response_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE response details. + */ +typedef struct +{ + uint32_t offset; //!< Used only when packet receipt notification is used. + uint32_t crc; //!< Used only when packet receipt notification is used. +} nrf_dfu_response_write_t; + +/** + * @brief @ref NRF_DFU_OP_CRC_GET response details. + */ +typedef struct +{ + uint32_t offset; //!< Current offset. + uint32_t crc; //!< Current CRC. +} nrf_dfu_response_crc_t; + +/** + * @brief @ref NRF_DFU_OP_PING response details. + */ +typedef struct +{ + uint8_t id; //!< The received ID which is echoed back. +} nrf_dfu_response_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET response details. + */ +typedef struct +{ + uint16_t size; //!< The MTU size as specified by the local transport. +} nrf_dfu_response_mtu_t; + +/** + * @brief DFU response message. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + nrf_dfu_result_t result; //!< Result of the operation. + union + { + nrf_dfu_response_protocol_t protocol; //!< Protocol version response. + nrf_dfu_response_hardware_t hardware; //!< Hardware version response. + nrf_dfu_response_firmware_t firmware; //!< Firmware version response. + nrf_dfu_response_select_t select; //!< Select object response.. + nrf_dfu_response_create_t create; //!< Create object response.. + nrf_dfu_response_write_t write; //!< Write object response. + nrf_dfu_response_crc_t crc; //!< CRC response. + nrf_dfu_response_ping_t ping; //!< Ping response. + nrf_dfu_response_mtu_t mtu; //!< MTU response. + }; +} nrf_dfu_response_t; + +/** + * @brief @ref NRF_DFU_OP_FIRMWARE_VERSION request details. + */ +typedef struct +{ + uint8_t image_number; //!< Index of the firmware. +} nrf_dfu_request_firmware_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_SELECT request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. +} nrf_dfu_request_select_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_CREATE request details. + */ +typedef struct +{ + uint32_t object_type; //!< Object type. See @ref nrf_dfu_obj_type_t. + uint32_t object_size; //!< Object size in bytes. +} nrf_dfu_request_create_t; + +/** + * @brief @ref NRF_DFU_OP_OBJECT_WRITE request details. + */ +typedef struct +{ + uint8_t const * p_data; //!< Data. + uint16_t len; //!< Length of data in @ref nrf_dfu_request_write_t::p_data. +} nrf_dfu_request_write_t; + +/** + * @brief @ref NRF_DFU_OP_PING request details. + */ +typedef struct +{ + uint8_t id; //!< Ping ID that will be returned in response. +} nrf_dfu_request_ping_t; + +/** + * @brief @ref NRF_DFU_OP_MTU_GET request details. + */ +typedef struct +{ + uint16_t size; //!< Transport MTU size in bytes. +} nrf_dfu_request_mtu_t; + +/** + * @brief @ref NRF_DFU_OP_RECEIPT_NOTIF_SET request details. + */ +typedef struct +{ + uint32_t target; //!< Target PRN. +} nrf_dfu_request_prn_t; + + +typedef void (*nrf_dfu_response_callback_t)(nrf_dfu_response_t * p_res, void * p_context); + +/** + *@brief DFU request. + */ +typedef struct +{ + nrf_dfu_op_t request; //!< Requested operation. + void * p_context; + struct + { + nrf_dfu_response_callback_t response; //!< Callback to call to send the response. + nrf_dfu_flash_callback_t write; + } callback; + union + { + nrf_dfu_request_firmware_t firmware; //!< Firmware version request. + nrf_dfu_request_select_t select; //!< Select object request. + nrf_dfu_request_create_t create; //!< Create object request. + nrf_dfu_request_write_t write; //!< Write object request. + nrf_dfu_request_ping_t ping; //!< Ping. + nrf_dfu_request_mtu_t mtu; //!< MTU size request. + nrf_dfu_request_prn_t prn; //!< Set receipt notification request. + }; +} nrf_dfu_request_t; + + +/**@brief Function for initializing the request handling module. + * + * @param observer Callback function for receiving notifications. + * + * @retval NRF_SUCCESS If the operation was successful. + * @retval NRF_ERROR_INTERNAL If the init packet in flash is not valid. + * @retval NRF_ERROR_INVALID_PARAM If observer is not provided. + */ +ret_code_t nrf_dfu_req_handler_init(nrf_dfu_observer_t observer); + + +/**@brief Function for scheduling processing of a DFU request. + * + * Requests are processed asynchronously by the scheduler. + * + * @param[in] p_req Request to be handled. The response callback must be non-null. + * + * @retval NRF_SUCCESS If the command request was executed successfully. + * @retval NRF_ERROR_NO_MEM If the scheduler ran out of memory. + * @retval NRF_ERROR_INVALID_PARAM If the response callback is NULL. + */ +ret_code_t nrf_dfu_req_handler_on_req(nrf_dfu_request_t * p_req); + + +ANON_UNIONS_DISABLE; + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_REQ_HANDLER_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c new file mode 100644 index 000000000..07146a8e2 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.c @@ -0,0 +1,423 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_settings.h" +#include +#include +#include "nrf_dfu_flash.h" +#include "nrf_soc.h" +#include "crc32.h" +#include "nrf_nvmc.h" +#include "sdk_config.h" + + +#define DFU_SETTINGS_VERSION_OFFSET (offsetof(nrf_dfu_settings_t, settings_version)) //crc != 0xFFFFFFFF) + { + // CRC is set. Content must be valid + uint32_t crc = settings_crc_get(p_settings); + if (crc == p_settings->crc) + { + return true; + } + } + return false; +} + + +static uint32_t boot_validation_crc(nrf_dfu_settings_t const * p_settings) +{ + return crc32_compute((const uint8_t *)&p_settings->boot_validation_softdevice, + DFU_SETTINGS_BOOT_VALIDATION_SIZE - 4, + NULL); +} + + +static bool boot_validation_crc_ok(nrf_dfu_settings_t const * p_settings) +{ + return (boot_validation_crc(p_settings) == p_settings->boot_validation_crc); +} + + +static bool settings_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)m_dfu_settings_buffer; + return crc_ok(p_settings); +} + + +static bool settings_backup_crc_ok(void) +{ + nrf_dfu_settings_t const * p_settings = (nrf_dfu_settings_t const *)mp_dfu_settings_backup_buffer; + return crc_ok(p_settings) && ((p_settings->settings_version == 1) || boot_validation_crc_ok(p_settings)); +} + +#define REGION_COPY_BY_MEMBER(start_member, end_member, p_dst_addr) \ + memcpy(p_dst_addr + offsetof(nrf_dfu_settings_t, start_member), \ + mp_dfu_settings_backup_buffer + offsetof(nrf_dfu_settings_t, start_member), \ + offsetof(nrf_dfu_settings_t, end_member) - offsetof(nrf_dfu_settings_t, start_member)) + + +static void settings_forbidden_parts_copy_from_backup(uint8_t * p_dst_addr) +{ +#if NRF_DFU_IN_APP || NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + REGION_COPY_BY_MEMBER(settings_version, bank_current, p_dst_addr); + REGION_COPY_BY_MEMBER(bank_0, write_offset, p_dst_addr); + REGION_COPY_BY_MEMBER(sd_size, progress, p_dst_addr); + REGION_COPY_BY_MEMBER(boot_validation_crc, peer_data, p_dst_addr); +#else + REGION_COPY_BY_MEMBER(settings_version, enter_buttonless_dfu, p_dst_addr); + REGION_COPY_BY_MEMBER(init_command, peer_data, p_dst_addr); +#endif +} + +void nrf_dfu_settings_reinit(void) +{ + bool settings_valid = settings_crc_ok(); + bool settings_backup_valid = settings_backup_crc_ok(); + + if (settings_valid) + { + NRF_LOG_DEBUG("Using settings page."); + memcpy(&s_dfu_settings, m_dfu_settings_buffer, sizeof(nrf_dfu_settings_t)); + if (settings_backup_valid) + { + NRF_LOG_DEBUG("Copying forbidden parts from backup page."); + settings_forbidden_parts_copy_from_backup((uint8_t *)&s_dfu_settings); + } + } + else if (settings_backup_valid) + { + NRF_LOG_INFO("Restoring settings from backup since the settings page contents are " + "invalid (CRC error)."); + memcpy(&s_dfu_settings, + mp_dfu_settings_backup_buffer, + sizeof(nrf_dfu_settings_t)); + } + else + { + NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page nor the " + "backup are valid (CRC error)."); + memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + if (NRF_DFU_SETTINGS_COMPATIBILITY_MODE && !NRF_DFU_IN_APP && (s_dfu_settings.settings_version == 1)) + { + NRF_LOG_WARNING("Resetting bootloader settings since neither the settings page is old."); + memset(&s_dfu_settings, 0x00, sizeof(nrf_dfu_settings_t)); + s_dfu_settings.settings_version = NRF_DFU_SETTINGS_VERSION; + } + + return; +} + +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized) +{ + NRF_LOG_DEBUG("Calling nrf_dfu_settings_init()..."); + + ret_code_t err_code = nrf_dfu_flash_init(sd_irq_initialized); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_flash_init() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + nrf_dfu_settings_reinit(); + + err_code = nrf_dfu_settings_write_and_backup(NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("nrf_dfu_settings_write_and_backup() failed with error: %x", err_code); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +static bool settings_forbidden_parts_equal_to_backup(uint8_t * p_compare_addr) +{ + nrf_dfu_settings_t temp_settings; + memcpy(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)); + settings_forbidden_parts_copy_from_backup((uint8_t *)&temp_settings); + return memcmp(&temp_settings, p_compare_addr, sizeof(nrf_dfu_settings_t)) == 0; +} + + +static ret_code_t settings_write(void * p_dst, + void const * p_src, + nrf_dfu_flash_callback_t callback, + nrf_dfu_settings_t * p_dfu_settings_buffer) +{ + ret_code_t err_code; + + if (memcmp(p_dst, p_src, sizeof(nrf_dfu_settings_t)) == 0) + { + NRF_LOG_DEBUG("Destination settings are identical to source, write not needed. Skipping."); + if (callback != NULL) + { + callback(NULL); + } + return NRF_SUCCESS; + } + + if (NRF_DFU_IN_APP && !settings_forbidden_parts_equal_to_backup((uint8_t *)&s_dfu_settings)) + { + NRF_LOG_WARNING("Settings write aborted since it tries writing to forbidden settings."); + return NRF_ERROR_FORBIDDEN; + } + + NRF_LOG_DEBUG("Writing settings..."); + NRF_LOG_DEBUG("Erasing old settings at: 0x%08x", p_dst); + + // Not setting the callback function because ERASE is required before STORE + // Only report completion on successful STORE. + err_code = nrf_dfu_flash_erase((uint32_t)p_dst, 1, NULL); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not erase the settings page!"); + return NRF_ERROR_INTERNAL; + } + + ASSERT(p_dfu_settings_buffer != NULL); + memcpy(p_dfu_settings_buffer, p_src, sizeof(nrf_dfu_settings_t)); + + err_code = nrf_dfu_flash_store((uint32_t)p_dst, + p_dfu_settings_buffer, + sizeof(nrf_dfu_settings_t), + callback); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not write the DFU settings page!"); + return NRF_ERROR_INTERNAL; + } + + return NRF_SUCCESS; +} + + +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback) +{ + static nrf_dfu_settings_t dfu_settings_buffer; + s_dfu_settings.crc = settings_crc_get(&s_dfu_settings); + s_dfu_settings.boot_validation_crc = boot_validation_crc(&s_dfu_settings); + return settings_write(m_dfu_settings_buffer, + &s_dfu_settings, + callback, + &dfu_settings_buffer); +} + + +void settings_backup(nrf_dfu_flash_callback_t callback, void * p_src) +{ +#if NRF_DFU_IN_APP + NRF_LOG_INFO("Settings backup not available from app."); +#else + static nrf_dfu_settings_t dfu_settings_buffer; + NRF_LOG_INFO("Backing up settings page to address 0x%x.", mp_dfu_settings_backup_buffer); + ASSERT(crc_ok(p_src)); + ret_code_t err_code = settings_write(mp_dfu_settings_backup_buffer, + p_src, + callback, + &dfu_settings_buffer); + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not perform backup of bootloader settings! Error: 0x%x", err_code); + } +#endif +} + + +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback) +{ + settings_backup(callback, m_dfu_settings_buffer); +} + + +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback) +{ +#if NRF_DFU_IN_APP + ret_code_t err_code = nrf_dfu_settings_write(callback); +#else + ret_code_t err_code = nrf_dfu_settings_write(NULL); + if (err_code == NRF_SUCCESS) + { + settings_backup(callback, &s_dfu_settings); + } +#endif + return err_code; +} + + +__WEAK ret_code_t nrf_dfu_settings_additional_erase(void) +{ + NRF_LOG_WARNING("No additional data erased"); + return NRF_SUCCESS; +} + + +void nrf_dfu_settings_progress_reset(void) +{ + memset(s_dfu_settings.init_command, 0xFF, INIT_COMMAND_MAX_SIZE); // Remove the last init command + memset(&s_dfu_settings.progress, 0, sizeof(dfu_progress_t)); + s_dfu_settings.write_offset = 0; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h new file mode 100644 index 000000000..10f2c82e9 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings.h @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_settings DFU settings + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_SETTINGS_H__ +#define NRF_DFU_SETTINGS_H__ + +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_flash.h" +#include "sdk_config.h" +#include "sdk_errors.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/**@brief Global settings. + * + * @note Using this variable is not thread-safe. + * + */ +extern nrf_dfu_settings_t s_dfu_settings; + + +/**@brief Function for writing DFU settings to flash. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_write(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for backing up the settings. + * + * This function copies the contents of the settings page (in flash) to a separate page (in flash). + * During @ref nrf_dfu_settings_init, the backup is restored if the original is invalid. + * + * @param[in] callback Pointer to a function that is called after completing the write operation. + */ +void nrf_dfu_settings_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for writing DFU settings to flash and to backup. + * + * This function first calls @ref nrf_dfu_settings_write and then @ref nrf_dfu_settings_backup. + * + * @param[in] callback Pointer to a function that is called after completing the write and backup operation. + * + * @retval NRF_SUCCESS If the write process was successfully initiated. + * @retval NRF_ERROR_INTERNAL If a flash error occurred during the first write. + */ +ret_code_t nrf_dfu_settings_write_and_backup(nrf_dfu_flash_callback_t callback); + + +/**@brief Function for initializing the DFU settings structure. + * + * Initializes the RAM structure from the flash contents. + * This function is called as part of @ref nrf_dfu_settings_init. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +void nrf_dfu_settings_reinit(void); + + +/**@brief Function for initializing the DFU settings module. + * + * @retval NRF_SUCCESS If the initialization was successful. + * @retval NRF_ERROR_INTERNAL If a flash error occurred. + */ +ret_code_t nrf_dfu_settings_init(bool sd_irq_initialized); + + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +/** @brief Function for storing peer data received through an SVCI call in DFU settings. + * + * @note The content of the type can be verified by a CRC value stored inside the struct + * If the CRC value is 0xFFFFFFFF, it means that no data is set. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_data Peer data to be stored in flash. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_data was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_peer_data_write(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for copying peer data from DFU settings to RAM. + * + * @param[in,out] p_data Structure to copy peer data to. + * + * @retval NRF_SUCCESS Peer data was successfully copied. + * @retval NRF_ERROR_NULL p_data was NULL. + */ +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data); + + +/** @brief Function for validating peer data in DFU settings. + * + * @retval True if peer data is validated by CRC, false if not. + */ +bool nrf_dfu_settings_peer_data_is_valid(void); + + +/** @brief Function for storing an advertisement name received through an SVCI call in DFU settings. + * + * @note The content of the type is verifyable by a CRC-value stored inside the struct. + * + * @note The storage operation is an asynchronous progress. Success will be notified + * through system events raised by the SoftDevice. + * + * @param[in] p_adv_name Structure holding information about the new advertisement name. + * + * @retval NRF_SUCCESS Asynchronous operation was successfully started. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + * @retval Any other error code reported by SoftDevice API calls. + */ +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for copying the advertisement name from DFU settings to RAM. + * + * @param[in,out] p_adv_name Structure to copy the new advertisement name to. + * + * @retval NRF_SUCCESS Advertisement name was successfully copied. + * @retval NRF_ERROR_NULL p_adv_name was NULL. + */ +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name); + + +/** @brief Function for validating advertisement data in DFU settings. + * + * @retval True if advertisement name is validated by CRC, false if not. + */ +bool nrf_dfu_settings_adv_name_is_valid(void); + +#endif // NRF_DFU_TRANSPORT_BLE + +/** @brief Function for erasing additional data in DFU settings. + * + * @note Erasing additional data in DFU settings is only possible + * if nrf_dfu_flash is initialized to not use SoftDevice calls. + * + * @retval NRF_SUCCESS Additional data was successfully erased. + * @retval Any other error code reported by nrf_dfu_flash + */ +ret_code_t nrf_dfu_settings_additional_erase(void); + +/** @brief Function for resetting both init command and DFU transfer progress inside settings structure. + * + * @note This function does not perform flash operation. + * In order to save the reset state, please use @ref nrf_dfu_settings_write function. + */ +void nrf_dfu_settings_progress_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_SETTINGS_H__ + +/**@} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c b/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c new file mode 100644 index 000000000..f16f0b417 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_settings_svci.c @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "app_error.h" +#include "sdk_macros.h" +#include "nrf_dfu_settings.h" +#include "nrf_nvmc.h" +#include "crc32.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_settings_svci +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#define DFU_SETTINGS_PEER_DATA_OFFSET offsetof(nrf_dfu_settings_t, peer_data) //crc = crc32_compute((uint8_t*)p_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_peer_data_settings, + (uint32_t*)p_data, + sizeof(nrf_dfu_peer_data_t)/4); + + return ret_val; +} + + +ret_code_t nrf_dfu_settings_peer_data_copy(nrf_dfu_peer_data_t * p_data) +{ + VERIFY_PARAM_NOT_NULL(p_data); + + memcpy(p_data, &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET], sizeof(nrf_dfu_peer_data_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_peer_data_is_valid(void) +{ + nrf_dfu_peer_data_t * p_peer_data = + (nrf_dfu_peer_data_t*) &m_dfu_settings_buffer[DFU_SETTINGS_PEER_DATA_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_peer_data + 4, sizeof(nrf_dfu_peer_data_t) - 4, NULL); + + return (p_peer_data->crc == crc); +} + +#else // not NRF_DFU_BLE_REQUIRES_BONDS + +ret_code_t nrf_dfu_settings_adv_name_write(nrf_dfu_adv_name_t * p_adv_name) +{ + uint32_t ret_val; + + uint32_t * p_adv_name_settings = + (uint32_t*) &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + uint32_t crc = (uint32_t)*p_adv_name_settings; + + VERIFY_PARAM_NOT_NULL(p_adv_name); + + if (crc != 0xFFFFFFFF) + { + // Already written to, must be cleared out. + // Reset required + return NRF_ERROR_INVALID_STATE; + } + + // Calculate the CRC for the structure excluding the CRC value itself. + p_adv_name->crc = crc32_compute((uint8_t *)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + // Using SoftDevice call since this function cannot use static memory. + ret_val = sd_flash_write(p_adv_name_settings, + (uint32_t*) p_adv_name, + sizeof(nrf_dfu_adv_name_t)/4); + return ret_val; +} + + +ret_code_t nrf_dfu_settings_adv_name_copy(nrf_dfu_adv_name_t * p_adv_name) +{ + VERIFY_PARAM_NOT_NULL(p_adv_name); + memcpy(p_adv_name, &m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET], sizeof(nrf_dfu_adv_name_t)); + + return NRF_SUCCESS; +} + + +bool nrf_dfu_settings_adv_name_is_valid(void) +{ + nrf_dfu_adv_name_t * p_adv_name = + (nrf_dfu_adv_name_t*)&m_dfu_settings_buffer[DFU_SETTINGS_ADV_NAME_OFFSET]; + + // Calculate the CRC for the structure excluding the CRC value itself. + uint32_t crc = crc32_compute((uint8_t*)p_adv_name + 4, sizeof(nrf_dfu_adv_name_t) - 4, NULL); + + return (p_adv_name->crc == crc); +} + +#endif + + +//lint -save -e(14) +ret_code_t nrf_dfu_settings_additional_erase(void) +{ + ret_code_t ret_code = NRF_SUCCESS; + + // Check CRC for both types. + if ( (s_dfu_settings.peer_data.crc != 0xFFFFFFFF) + || (s_dfu_settings.adv_name.crc != 0xFFFFFFFF)) + { + NRF_LOG_DEBUG("Erasing settings page additional data."); + + // Erasing and resetting the settings page without the peer data/adv data + nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS); + nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t const *)&s_dfu_settings, DFU_SETTINGS_PEER_DATA_OFFSET / 4); + } + + return ret_code; +} +//lint -restore + diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c b/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c new file mode 100644 index 000000000..2821ec3da --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_svci.c @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include "nrf_log.h" +#include "nrf_sdm.h" +#include "app_util.h" + +#define APP_START_ADDR CODE_START + + +uint32_t nrf_dfu_svci_vector_table_set(void) +{ + uint32_t err_code; + uint32_t bootloader_addr = BOOTLOADER_ADDRESS; + + if (bootloader_addr != 0xFFFFFFFF) + { + NRF_LOG_INFO("Setting vector table to bootloader: 0x%08x", bootloader_addr); + err_code = sd_softdevice_vector_table_base_set(bootloader_addr); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; + } + + NRF_LOG_ERROR("No bootloader was found"); + return NRF_ERROR_NO_MEM; +} + + +uint32_t nrf_dfu_svci_vector_table_unset(void) +{ + uint32_t err_code; + + NRF_LOG_INFO("Setting vector table to main app: 0x%08x", APP_START_ADDR); + err_code = sd_softdevice_vector_table_base_set(APP_START_ADDR); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed running sd_softdevice_vector_table_base_set"); + return err_code; + } + + return NRF_SUCCESS; +} + diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c b/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c new file mode 100644 index 000000000..bb1768aae --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_svci_handler.c @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include "nrf_svci_async_handler.h" +#include "app_error.h" +#include "nrf_nvmc.h" +#include "nrf_dfu_types.h" +#include "nrf_dfu_ble_svci_bond_sharing.h" +#include "nrf_log.h" +#include "nrf_dfu_settings.h" +#include "sdk_config.h" + + +#if (NRF_DFU_TRANSPORT_BLE && NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_PEER_DATA, + nrf_dfu_set_peer_data, nrf_dfu_peer_data_t, nrf_dfu_peer_data_state_t); + + +static uint32_t nrf_dfu_set_peer_data_handler(nrf_dfu_set_peer_data_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_peer_data_on_call; + p_async->sys_evt_handler = nrf_dfu_set_peer_data_on_sys_evt; + p_async->state = DFU_PEER_DATA_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_peer_data_on_call(nrf_dfu_peer_data_t * p_data, + nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_PEER_DATA_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_peer_data_write(p_data); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_PEER_DATA_STATE_WRITE_REQUESTED; + } + break; + + case DFU_PEER_DATA_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_PEER_DATA_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_PEER_DATA_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_peer_data_on_sys_evt(uint32_t sys_event, nrf_dfu_peer_data_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_PEER_DATA_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_PEER_DATA_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#elif (NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS) + + +NRF_SVCI_ASYNC_HANDLER_CREATE(NRF_DFU_SVCI_SET_ADV_NAME, + nrf_dfu_set_adv_name, nrf_dfu_adv_name_t, nrf_dfu_set_adv_name_state_t); + + +static uint32_t nrf_dfu_set_adv_name_handler(nrf_dfu_set_adv_name_svci_async_t * p_async) +{ + VERIFY_PARAM_NOT_NULL(p_async); + + p_async->async_func = nrf_dfu_set_adv_name_on_call; + p_async->sys_evt_handler = nrf_dfu_set_adv_name_on_sys_evt; + p_async->state = DFU_ADV_NAME_STATE_INITIALIZED; + + return NRF_SUCCESS; +} + + +static uint32_t nrf_dfu_set_adv_name_on_call(nrf_dfu_adv_name_t * p_adv_name, + nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_BUSY; + + VERIFY_PARAM_NOT_NULL(p_state); + + switch (*p_state) + { + case DFU_ADV_NAME_STATE_INVALID: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_INITIALIZED: + ret_val = nrf_dfu_settings_adv_name_write(p_adv_name); + if (ret_val == NRF_SUCCESS) + { + *p_state = DFU_ADV_NAME_STATE_WRITE_REQUESTED; + } + break; + + case DFU_ADV_NAME_STATE_WRITE_REQUESTED: + return NRF_ERROR_BUSY; + + case DFU_ADV_NAME_STATE_WRITE_FINISHED: + return NRF_ERROR_INVALID_STATE; + + case DFU_ADV_NAME_STATE_WRITE_FAILED: + return NRF_ERROR_INVALID_STATE; + } + + return ret_val; +} + + +static uint32_t nrf_dfu_set_adv_name_on_sys_evt(uint32_t sys_event, nrf_dfu_set_adv_name_state_t * p_state) +{ + uint32_t ret_val = NRF_ERROR_INVALID_STATE; + + VERIFY_PARAM_NOT_NULL(p_state); + + if (*p_state == DFU_ADV_NAME_STATE_WRITE_REQUESTED) + { + switch (sys_event) + { + case NRF_EVT_FLASH_OPERATION_ERROR: + return NRF_ERROR_BUSY; + + case NRF_EVT_FLASH_OPERATION_SUCCESS: + ret_val = NRF_SUCCESS; + (*p_state) = DFU_ADV_NAME_STATE_WRITE_FINISHED; + break; + + default: + // Event not intended for us + break; + } + } + + return ret_val; +} + +#endif // NRF_DFU_TRANSPORT_BLE && !NRF_DFU_BLE_REQUIRES_BONDS diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c new file mode 100644 index 000000000..cb6e9a49d --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.c @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_transport.h" +#include "nrf_log.h" + + +#define DFU_TRANS_SECTION_ITEM_GET(i) NRF_SECTION_ITEM_GET(dfu_trans, nrf_dfu_transport_t, (i)) +#define DFU_TRANS_SECTION_ITEM_COUNT NRF_SECTION_ITEM_COUNT(dfu_trans, nrf_dfu_transport_t) + +NRF_SECTION_DEF(dfu_trans, const nrf_dfu_transport_t); + + +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Initializing transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->init_func(observer); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to initialize transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} + + +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception) +{ + uint32_t const num_transports = DFU_TRANS_SECTION_ITEM_COUNT; + uint32_t ret_val = NRF_SUCCESS; + + NRF_LOG_DEBUG("Shutting down transports (found: %d)", num_transports); + + for (uint32_t i = 0; i < num_transports; i++) + { + nrf_dfu_transport_t * const trans = DFU_TRANS_SECTION_ITEM_GET(i); + ret_val = trans->close_func(p_exception); + if (ret_val != NRF_SUCCESS) + { + NRF_LOG_DEBUG("Failed to shutdown transport %d, error %d", i, ret_val); + break; + } + } + + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h new file mode 100644 index 000000000..e10723ec5 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_transport.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_transport DFU transport + * @{ + * @ingroup nrf_dfu + * @brief Generic Device Firmware Update (DFU) transport interface. + * + * @details The DFU transport module defines a generic interface that must + * be implemented for each transport layer. + */ + +#ifndef NRF_DFU_TRANSPORT_H__ +#define NRF_DFU_TRANSPORT_H__ + +#include +#include "nrf_section.h" +#include "nrf_dfu_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Forward declaration of nrf_dfu_transport_t */ +typedef struct nrf_dfu_transport_s nrf_dfu_transport_t; + +/** @brief Function type for initializing a DFU transport. + * + * @details This function initializes a DFU transport. The implementation + * of the function must initialize DFU mode and stay in service + * until either the device is reset or the DFU operation is finalized. + * When the DFU transport receives requests, it should call @ref nrf_dfu_req_handler_on_req for handling the requests. + * + * @param observer Callback function for receiving DFU transport notifications. + * + * @retval NRF_SUCCESS If initialization was successful for the transport. Any other return code indicates that the DFU transport could not be initialized. + */ +typedef uint32_t (*nrf_dfu_init_fn_t)(nrf_dfu_observer_t observer); + + +/** @brief Function type for closing down a DFU transport. + * + * @details This function closes down a DFU transport in a gentle way. + * + * @param[in] p_exception If exception matches current transport closing should be omitted. + * + * @retval NRF_SUCCESS If closing was successful for the transport. Any other return code indicates that the DFU transport could not be closed closed down. + */ +typedef uint32_t (*nrf_dfu_close_fn_t)(nrf_dfu_transport_t const * p_exception); + + + +/** @brief DFU transport registration. + * + * @details Every DFU transport must provide a registration of the initialization function. + */ +struct nrf_dfu_transport_s +{ + nrf_dfu_init_fn_t init_func; /**< Registration of the init function to run to initialize a DFU transport. */ + nrf_dfu_close_fn_t close_func; /**< Registration of the close function to close down a DFU transport. */ +}; + + +/** @brief Function for initializing all the registered DFU transports. + * + * @retval NRF_SUCCESS If all DFU transport were initialized successfully. + * Any other error code indicates that at least one DFU + * transport could not be initialized. + */ +uint32_t nrf_dfu_transports_init(nrf_dfu_observer_t observer); + +/** @brief Function for closing down all (with optional exception) the registered DFU transports. + * + * @param[in] p_exception Transport which should not be closed. NULL if all transports should be closed. + * @retval NRF_SUCCESS If all DFU transport were closed down successfully. + * Any other error code indicates that at least one DFU + * transport could not be closed down. + */ +uint32_t nrf_dfu_transports_close(nrf_dfu_transport_t const * p_exception); + + +/** @brief Macro for registering a DFU transport by using section variables. + * + * @details This macro places a variable in a section named "dfu_trans", which + * is initialized by @ref nrf_dfu_transports_init. + */ +#define DFU_TRANSPORT_REGISTER(trans_var) NRF_SECTION_ITEM_REGISTER(dfu_trans, trans_var) + + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TRANSPORT_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c new file mode 100644 index 000000000..90b69290a --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.c @@ -0,0 +1,244 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_trigger_usb.h" +#include "app_usbd.h" +#include "app_usbd_nrf_dfu_trigger.h" +#include "nrf_drv_clock.h" +#include "nrf_log_ctrl.h" +#include "nrf_gpio.h" +#include "boards.h" +#include "app_util.h" +#include "app_usbd_serial_num.h" +#define NRF_LOG_MODULE_NAME nrf_dfu_trigger_usb +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef BSP_SELF_PINRESET_PIN +#error "This module is intended to be used with boards that have the GP pin shortened with the RESET pin." +#endif + +/** + * @brief Enable power USB detection. + * + * Configure if the example supports USB port connection. + */ +#ifndef USBD_POWER_DETECTION +#define USBD_POWER_DETECTION true +#endif + +#define DFU_FLASH_PAGE_SIZE (NRF_FICR->CODEPAGESIZE) +#define DFU_FLASH_PAGE_COUNT (NRF_FICR->CODESIZE) + +// Semantic versioning string. +#define VERSION_STRING STRINGIFY(APP_VERSION_MAJOR) "." STRINGIFY(APP_VERSION_MINOR) "." STRINGIFY(APP_VERSION_PATCH) APP_VERSION_PRERELEASE APP_VERSION_METADATA + +static uint8_t m_version_string[] = APP_NAME " " VERSION_STRING; ///< Human-readable version string. +static app_usbd_nrf_dfu_trigger_nordic_info_t m_dfu_info; ///< Struct with various information about the current firmware. + +static void dfu_trigger_evt_handler(app_usbd_class_inst_t const * p_inst, + app_usbd_nrf_dfu_trigger_user_event_t event) +{ + UNUSED_PARAMETER(p_inst); + + switch (event) + { + case APP_USBD_NRF_DFU_TRIGGER_USER_EVT_DETACH: + NRF_LOG_INFO("DFU Detach request received. Triggering a pin reset."); + NRF_LOG_FINAL_FLUSH(); + nrf_gpio_cfg_output(BSP_SELF_PINRESET_PIN); + nrf_gpio_pin_clear(BSP_SELF_PINRESET_PIN); + break; + default: + break; + } +} + + +APP_USBD_NRF_DFU_TRIGGER_GLOBAL_DEF(m_app_dfu, + NRF_DFU_TRIGGER_USB_INTERFACE_NUM, + &m_dfu_info, + m_version_string, + dfu_trigger_evt_handler); + + +static void usbd_user_evt_handler(app_usbd_event_type_t event) +{ + switch (event) + { + case APP_USBD_EVT_DRV_SUSPEND: + break; + case APP_USBD_EVT_DRV_RESUME: + break; + case APP_USBD_EVT_STARTED: + break; + case APP_USBD_EVT_STOPPED: + app_usbd_disable(); + break; + case APP_USBD_EVT_POWER_DETECTED: + NRF_LOG_INFO("USB power detected"); + + if (!nrf_drv_usbd_is_enabled()) + { + app_usbd_enable(); + } + break; + case APP_USBD_EVT_POWER_REMOVED: + NRF_LOG_INFO("USB power removed"); + app_usbd_stop(); + break; + case APP_USBD_EVT_POWER_READY: + NRF_LOG_INFO("USB ready"); + app_usbd_start(); + break; + default: + break; + } +} + + +static void strings_create(void) +{ + uint8_t prev_char = 'a'; // Arbitrary valid char, not '-'. + + // Remove characters that are not supported in semantic version strings. + for (size_t i = strlen(APP_NAME) + 1; i < strlen((char*)m_version_string); i++) + { + if (((m_version_string[i] >= 'a') && (m_version_string[i] <= 'z')) + || ((m_version_string[i] >= 'A') && (m_version_string[i] <= 'Z')) + || ((m_version_string[i] >= '0') && (m_version_string[i] <= '9')) + || (m_version_string[i] == '+') + || (m_version_string[i] == '.') + || (m_version_string[i] == '-')) + { + // Valid semantic version character. + } + else if (prev_char == '-') + { + m_version_string[i] = '0'; + } + else + { + m_version_string[i] = '-'; + } + + prev_char = m_version_string[i]; + } + +#if !NRF_DFU_TRIGGER_USB_USB_SHARED + app_usbd_serial_num_generate(); +#endif +} + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) +static void usbd_evt_handler(app_usbd_internal_evt_t const * const p_event) +{ + app_usbd_event_execute(p_event); +} +#endif + +ret_code_t nrf_dfu_trigger_usb_init(void) +{ + ret_code_t ret; + static bool initialized = false; + + if (initialized) + { + return NRF_SUCCESS; + } + + m_dfu_info.wAddress = CODE_START; + m_dfu_info.wFirmwareSize = CODE_SIZE; + m_dfu_info.wVersionMajor = APP_VERSION_MAJOR; + m_dfu_info.wVersionMinor = APP_VERSION_MINOR; + m_dfu_info.wFirmwareID = APP_ID; + m_dfu_info.wFlashPageSize = DFU_FLASH_PAGE_SIZE; + m_dfu_info.wFlashSize = m_dfu_info.wFlashPageSize * DFU_FLASH_PAGE_COUNT; + + strings_create(); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + static const app_usbd_config_t usbd_config = { + +#if !(APP_USBD_CONFIG_EVENT_QUEUE_ENABLE) + .ev_handler = usbd_evt_handler, +#endif + .ev_state_proc = usbd_user_evt_handler + }; + + ret = nrf_drv_clock_init(); + if ((ret != NRF_SUCCESS) && (ret != NRF_ERROR_MODULE_ALREADY_INITIALIZED)) + { + return ret; + } + + ret = app_usbd_init(&usbd_config); + if (ret != NRF_SUCCESS) + { + return ret; + } + } + + app_usbd_class_inst_t const * class_dfu = app_usbd_nrf_dfu_trigger_class_inst_get(&m_app_dfu); + ret = app_usbd_class_append(class_dfu); + + if (!NRF_DFU_TRIGGER_USB_USB_SHARED) + { + if (USBD_POWER_DETECTION) + { + ret = app_usbd_power_events_enable(); + APP_ERROR_CHECK(ret); + } + else + { + NRF_LOG_INFO("No USB power detection enabled\r\nStarting USB now"); + + app_usbd_enable(); + app_usbd_start(); + } + } + + if (ret == NRF_SUCCESS) + { + initialized = true; + } + + return ret; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h new file mode 100644 index 000000000..01526361e --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_trigger_usb.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_DFU_TRIGGER_USB_H +#define NRF_DFU_TRIGGER_USB_H + +#include "sdk_errors.h" + +/** + * @defgroup nrf_dfu_trigger_usb USB DFU trigger library + * @ingroup app_common + * + * @brief @tagAPI52840 USB DFU trigger library is used to enter the bootloader and read the firmware version. + * + * @details See @ref lib_dfu_trigger_usb for additional documentation. + * @{ + */ + +/** + * @brief Function for initializing the USB DFU trigger library. + * + * @note If the USB is also used for other purposes, then this function must be called after USB is + * initialized but before it is enabled. In this case, the configuration flag @ref + * NRF_DFU_TRIGGER_USB_USB_SHARED must be set to 1. + * + * @note Calling this again after the first success has no effect and returns @ref NRF_SUCCESS. + * + * @note If @ref APP_USBD_CONFIG_EVENT_QUEUE_ENABLE is on (1), USB events must be handled manually. + * See @ref app_usbd_event_queue_process. + * + * @retval NRF_SUCCESS On successful initialization. + * @return An error code on failure, for example if called at a wrong time. + */ +ret_code_t nrf_dfu_trigger_usb_init(void); + +/** @} */ + +#endif //NRF_DFU_TRIGGER_USB_H diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_types.h b/core/embed/ble_bootloader/dfu/nrf_dfu_types.h new file mode 100644 index 000000000..81bc44d65 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_types.h @@ -0,0 +1,342 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_types DFU types + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_TYPES_H__ +#define NRF_DFU_TYPES_H__ + +#include +#include + +#include "sdk_common.h" +#include "nrf.h" +#include "nrf_mbr.h" +#include "app_util_platform.h" +#include "sdk_config.h" + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE +#include "ble_gap.h" +#define SYSTEM_SERVICE_ATT_SIZE 8 /**< Size of the system service attribute length including CRC-16 at the end. */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +#define INIT_COMMAND_MAX_SIZE 512 /**< Maximum size of the init command stored in dfu_settings. */ +#define INIT_COMMAND_MAX_SIZE_v1 256 /**< Maximum size of the init command in settings version 1. */ + +/** @brief Size of a flash page. This value is used for calculating the size of the reserved + * flash space in the bootloader region. + */ +#if defined(NRF51) + #define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#elif defined(NRF52_SERIES) + #define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#else + #error "Architecture not set." +#endif + +/** @brief Maximum size of a data object.*/ +#if defined(NRF51) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4) +#elif defined(NRF52_SERIES) || defined (__SDK_DOXYGEN__) + #define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE) +#else + #error "Architecture not set." +#endif + +/** @brief Page location of the bootloader settings address. + */ +#if defined (NRF51) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003FC00UL) +#elif defined( NRF52810_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52811_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL) +#elif defined( NRF52820_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0003F000UL) +#elif defined( NRF52832_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined( NRF52833_XXAA ) + #define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL) +#elif defined(NRF52840_XXAA) + #define BOOTLOADER_SETTINGS_ADDRESS (0x000FF000UL) +#else + #error No valid target set for BOOTLOADER_SETTINGS_ADDRESS. +#endif + +#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE) +#define NRF_MBR_PARAMS_PAGE_SIZE (CODE_PAGE_SIZE) + +/** @brief Page location of the MBR parameters page address. + */ +#if defined(NRF52840_XXAA) || defined(NRF52840_XXAA_ENGA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x000FE000UL) +#elif defined(NRF52832_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52833_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL) +#elif defined(NRF52810_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52811_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL) +#elif defined(NRF52820_XXAA) + #define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0003E000UL) +#endif + +#define BOOTLOADER_SETTINGS_BACKUP_ADDRESS NRF_MBR_PARAMS_PAGE_ADDRESS + + +#ifndef NRF_DFU_APP_DATA_AREA_SIZE +#define NRF_DFU_APP_DATA_AREA_SIZE (CODE_PAGE_SIZE * 3) +#endif + +STATIC_ASSERT((NRF_DFU_APP_DATA_AREA_SIZE % CODE_PAGE_SIZE) == 0, "NRF_DFU_APP_DATA_AREA_SIZE must be a multiple of the flash page size."); + +#define DFU_APP_DATA_RESERVED NRF_DFU_APP_DATA_AREA_SIZE // For backward compatibility with 15.0.0. + +/** @brief Total size of the region between the SoftDevice and the bootloader. + */ +#define DFU_REGION_END(bootloader_start_addr) ((bootloader_start_addr) - (NRF_DFU_APP_DATA_AREA_SIZE)) + +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REGION_START (nrf_dfu_bank0_start_addr()) +#else +#define DFU_REGION_START (MBR_SIZE) +#endif + +#define DFU_REGION_TOTAL_SIZE ((DFU_REGION_END) - (DFU_REGION_START)) + +#define NRF_DFU_CURRENT_BANK_0 0x00 +#define NRF_DFU_CURRENT_BANK_1 0x01 + +#define NRF_DFU_BANK_LAYOUT_DUAL 0x00 +#define NRF_DFU_BANK_LAYOUT_SINGLE 0x01 + +/** @brief DFU bank state codes. + * + * @details The DFU bank state indicates the content of a bank: + * A valid image of a certain type or an invalid image. + */ + +#define NRF_DFU_BANK_INVALID 0x00 /**< Invalid image. */ +#define NRF_DFU_BANK_VALID_APP 0x01 /**< Valid application. */ +#define NRF_DFU_BANK_VALID_SD 0xA5 /**< Valid SoftDevice. */ +#define NRF_DFU_BANK_VALID_BL 0xAA /**< Valid bootloader. */ +#define NRF_DFU_BANK_VALID_SD_BL 0xAC /**< Valid SoftDevice and bootloader. */ +#define NRF_DFU_BANK_VALID_EXT_APP 0xB1 /**< Valid application designated for a remote node. */ + +/** @brief Description of a single bank. */ +#pragma pack(4) +typedef struct +{ + uint32_t image_size; /**< Size of the image in the bank. */ + uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */ + uint32_t bank_code; /**< Identifier code for the bank. */ +} nrf_dfu_bank_t; + +/**@brief DFU progress. + * + * Be aware of the difference between objects and firmware images. A firmware image consists of multiple objects, each of a maximum size @ref DATA_OBJECT_MAX_SIZE. + * + * @note The union inside this struct is cleared when CREATE_OBJECT of command type is executed, and when there is a valid post-validation. + * In DFU activation (after reset) the @ref dfu_progress_t::update_start_address will be used in case of a SD/SD+BL update. + */ +ANON_UNIONS_ENABLE; +typedef struct +{ + uint32_t command_size; /**< The size of the current init command stored in the DFU settings. */ + uint32_t command_offset; /**< The offset of the currently received init command data. The offset will increase as the init command is received. */ + uint32_t command_crc; /**< The calculated CRC of the init command (calculated after the transfer is completed). */ + uint32_t data_object_size; /**< The size of the last object created. Note that this size is not the size of the whole firmware image.*/ + union + { + struct + { + uint32_t firmware_image_crc; /**< CRC value of the current firmware (continuously calculated as data is received). */ + uint32_t firmware_image_crc_last; /**< The CRC of the last executed object. */ + uint32_t firmware_image_offset; /**< The offset of the current firmware image being transferred. Note that this offset is the offset in the entire firmware image and not only the current object. */ + uint32_t firmware_image_offset_last;/**< The offset of the last executed object from the start of the firmware image. */ + }; + struct + { + uint32_t update_start_address; /**< Value indicating the start address of the new firmware (before copy). It's always used, but it's most important for an SD/SD+BL update where the SD changes size or if the DFU process had a power loss when updating a SD with changed size. */ + }; + }; +} dfu_progress_t; +ANON_UNIONS_DISABLE; + +/** @brief Event types in the bootloader and DFU process. */ +typedef enum +{ + NRF_DFU_EVT_DFU_INITIALIZED, /**< Starting DFU. */ + NRF_DFU_EVT_TRANSPORT_ACTIVATED, /**< Transport activated (e.g. BLE connected, USB plugged in). */ + NRF_DFU_EVT_TRANSPORT_DEACTIVATED, /**< Transport deactivated (e.g. BLE disconnected, USB plugged out). */ + NRF_DFU_EVT_DFU_STARTED, /**< DFU process started. */ + NRF_DFU_EVT_OBJECT_RECEIVED, /**< A DFU data object has been received. */ + NRF_DFU_EVT_DFU_FAILED, /**< DFU process has failed, been interrupted, or hung. */ + NRF_DFU_EVT_DFU_COMPLETED, /**< DFU process completed. */ + NRF_DFU_EVT_DFU_ABORTED, /**< DFU process aborted. */ +} nrf_dfu_evt_type_t; + +/** + * @brief Function for notifying DFU state. + */ +typedef void (*nrf_dfu_observer_t)(nrf_dfu_evt_type_t notification); + +#define NRF_DFU_PEER_DATA_LEN 64 /**< The length in bytes of nrf_dfu_peer_data_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ +#define NRF_DFU_ADV_NAME_LEN 28 /**< The length in bytes of nrf_dfu_adv_name_t expected by tools manipulating the settings page. Do not change without changing the settings page version. */ + +#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. */ + ble_gap_id_key_t ble_id; /**< BLE GAP identity key of the device that initiated the DFU process. */ + ble_gap_enc_key_t enc_key; /**< Encryption key structure containing encrypted diversifier and LTK for reestablishing the bond. */ + uint8_t sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**< System service attributes for restoring of Service Changed Indication setting in DFU mode. */ +} nrf_dfu_peer_data_t; + +typedef enum +{ + DFU_PEER_DATA_STATE_INVALID = 0, + DFU_PEER_DATA_STATE_INITIALIZED = 1, + DFU_PEER_DATA_STATE_WRITE_REQUESTED = 2, + DFU_PEER_DATA_STATE_WRITE_FINISHED = 3, + DFU_PEER_DATA_STATE_WRITE_FAILED = 4, +} nrf_dfu_peer_data_state_t; + +typedef struct +{ + uint32_t crc; /**< CRC of the rest of the parameters in this struct. Calculated by the bootloader. */ + uint8_t name[20]; /**< New advertisement name to set. */ + uint32_t len; /**< Length of the advertisement name. */ +} nrf_dfu_adv_name_t; + +typedef enum +{ + DFU_ADV_NAME_STATE_INVALID = 0, + DFU_ADV_NAME_STATE_INITIALIZED = 1, + DFU_ADV_NAME_STATE_WRITE_REQUESTED = 2, + DFU_ADV_NAME_STATE_WRITE_FINISHED = 3, + DFU_ADV_NAME_STATE_WRITE_FAILED = 4, +} nrf_dfu_set_adv_name_state_t; + +#else +typedef struct +{ + uint8_t dummy_data[NRF_DFU_PEER_DATA_LEN]; +} nrf_dfu_peer_data_t; + +typedef struct +{ + uint8_t dummy_data[NRF_DFU_ADV_NAME_LEN]; +} nrf_dfu_adv_name_t; +#endif // NRF_DFU_TRANSPORT_BLE + +STATIC_ASSERT(sizeof(nrf_dfu_peer_data_t) == NRF_DFU_PEER_DATA_LEN, "nrf_dfu_peer_data_t has unexpected length. This can cause incompatibility with tools."); +STATIC_ASSERT(sizeof(nrf_dfu_adv_name_t) == NRF_DFU_ADV_NAME_LEN, "nrf_dfu_adv_name_t has unexpected length. This can cause incompatibility with tools."); + +#define SETTINGS_RESERVED_AREA_SIZE 16 /**< The number of words in the reserved area of the DFU settings. */ +#define SETTINGS_BOOT_VALIDATION_SIZE 64 /**< The number of bytes reserved for boot_validation value. */ + + +typedef enum +{ + NO_VALIDATION, + VALIDATE_CRC, + VALIDATE_SHA256, + VALIDATE_ECDSA_P256_SHA256, +} boot_validation_type_t; + +typedef struct +{ + uint32_t sigmask; + uint8_t bytes[SETTINGS_BOOT_VALIDATION_SIZE]; +} boot_validation_t; + +/**@brief DFU settings for application and bank data. + */ +typedef struct +{ + uint32_t crc; /**< CRC for the stored DFU settings, not including the CRC itself. If 0xFFFFFFF, the CRC has never been calculated. */ + uint32_t settings_version; /**< Version of the current DFU settings struct layout. */ + uint32_t app_version; /**< Version of the last stored application. */ + uint32_t bootloader_version; /**< Version of the last stored bootloader. */ + + uint32_t bank_layout; /**< Bank layout: single bank or dual bank. This value can change. */ + uint32_t bank_current; /**< The bank that is currently used. */ + + nrf_dfu_bank_t bank_0; /**< Bank 0. */ + nrf_dfu_bank_t bank_1; /**< Bank 1. */ + + uint32_t write_offset; /**< Write offset for the current operation. */ + uint32_t sd_size; /**< Size of the SoftDevice. */ + + dfu_progress_t progress; /**< Current DFU progress. */ + + uint32_t enter_buttonless_dfu; + uint8_t init_command[INIT_COMMAND_MAX_SIZE]; /**< Buffer for storing the init command. */ + + uint32_t boot_validation_crc; + boot_validation_t boot_validation_softdevice; + boot_validation_t boot_validation_app; + boot_validation_t boot_validation_bootloader; + + nrf_dfu_peer_data_t peer_data; /**< Not included in calculated CRC. */ + nrf_dfu_adv_name_t adv_name; /**< Not included in calculated CRC. */ +} nrf_dfu_settings_t; + +#pragma pack() // revert pack settings + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_TYPES_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c new file mode 100644 index 000000000..978369a72 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.c @@ -0,0 +1,220 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_dfu_utils.h" + +#include "nrf_dfu_settings.h" +#include "nrf_bootloader_info.h" +#include "crc32.h" +#include "nrf_log.h" +#include "nrf_dfu_validation.h" + +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank) +{ + // Set the bank-code to invalid, and reset size/CRC + memset(p_bank, 0, sizeof(nrf_dfu_bank_t)); + + // Reset write pointer after completed operation + s_dfu_settings.write_offset = 0; +} + + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +void nrf_dfu_softdevice_invalidate(void) +{ + static const uint32_t all_zero = 0UL; + + if (SD_PRESENT && !NRF_DFU_IN_APP) + { + ret_code_t err_code = nrf_dfu_flash_store(SD_MAGIC_NUMBER_ABS_OFFSET_GET(MBR_SIZE), &all_zero, 4, NULL); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Could not invalidate SoftDevice.") + } + else + { + // If there is an app it must be invalidated since its start address can no longer be resolved. + if (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP) + { + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + } + // Since the start of bank 0 has now implicitly been moved to the start + // of the invalidated SoftDevice, its image size must be increased by the + // same amount so the start of bank 1 will be correctly calculated. + s_dfu_settings.bank_0.image_size += SD_SIZE_GET(MBR_SIZE) - MBR_SIZE; + } + } +} +#endif + + +uint32_t nrf_dfu_bank0_start_addr(void) +{ + if (SD_PRESENT) + { + return ALIGN_TO_PAGE(SD_SIZE_GET(MBR_SIZE)); + } + else + { + return MBR_SIZE; + } +} + + +uint32_t nrf_dfu_bank1_start_addr(void) +{ + uint32_t bank0_addr = nrf_dfu_bank0_start_addr(); + return ALIGN_TO_PAGE(bank0_addr + s_dfu_settings.bank_0.image_size); +} + + +uint32_t nrf_dfu_app_start_address(void) +{ + return nrf_dfu_bank0_start_addr(); +} + + +uint32_t nrf_dfu_softdevice_start_address(void) +{ + return MBR_SIZE; +} + + +uint32_t nrf_dfu_cache_prepare(const uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice) +{ + ret_code_t err_code; + bool cache_too_small; + enum + { + INITIAL_DELETE_APP = 0, + APP_DELETED_DELETE_SOFTDEVICE = 1, + SOFTDEVICE_DELETED = 2 + } pass; + + NRF_LOG_DEBUG("Enter nrf_dfu_cache_prepare()"); + NRF_LOG_DEBUG("required_size: 0x%x.", required_size); + NRF_LOG_DEBUG("single_bank: %s.", single_bank ? "true" : "false"); + NRF_LOG_DEBUG("keep_app: %s.", keep_app ? "true" : "false"); + NRF_LOG_DEBUG("keep_softdevice: %s.", keep_softdevice ? "true" : "false"); + NRF_LOG_DEBUG("SD_PRESENT: %s.", SD_PRESENT ? "true" : "false"); + NRF_LOG_DEBUG("Bank contents:"); + NRF_LOG_DEBUG("Bank 0 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_0.bank_code, s_dfu_settings.bank_0.image_size); + NRF_LOG_DEBUG("Bank 1 code: 0x%02x: Size: 0x%x", s_dfu_settings.bank_1.bank_code, s_dfu_settings.bank_1.image_size); + + // Pass 0 deletes the app if necessary or requested, and if so, proceeds to pass 1. + // Pass 1 deletes the SoftDevice if necessary or requested, and if so, proceeds to pass 2. + // Pass 2 does a last size check. + for (pass = INITIAL_DELETE_APP; pass <= SOFTDEVICE_DELETED; pass++) + { + uint32_t cache_address; + const uint32_t bootloader_start_addr = BOOTLOADER_START_ADDR; // Assign to a variable to prevent warning in Keil 4. + bool keep_firmware = true; + bool delete_more; + + switch (pass) + { + case INITIAL_DELETE_APP: + cache_address = nrf_dfu_bank1_start_addr(); + + // If there is no app, keep_app should be assumed false, so we can free up more space. + keep_firmware = keep_app && (s_dfu_settings.bank_0.bank_code == NRF_DFU_BANK_VALID_APP); + break; + + case APP_DELETED_DELETE_SOFTDEVICE: + cache_address = nrf_dfu_bank0_start_addr(); + + // If there is no SoftDevice, keep_SoftDevice should be assumed true, because there is + // no point to continuing since the SoftDevice is the last firmware that can be deleted. + keep_firmware = keep_softdevice || !SD_PRESENT; + break; + + case SOFTDEVICE_DELETED: + cache_address = nrf_dfu_softdevice_start_address(); + break; + + default: + ASSERT(false); + cache_address = 0; + break; + } + + ASSERT(cache_address <= DFU_REGION_END(bootloader_start_addr)); + cache_too_small = required_size > (DFU_REGION_END(bootloader_start_addr) - cache_address); + delete_more = cache_too_small || single_bank; // Delete app or SoftDevice only if we need more room, or if single bank is requested. + + NRF_LOG_DEBUG("pass: %d.", pass); + NRF_LOG_DEBUG("cache_address: 0x%x.", cache_address); + NRF_LOG_DEBUG("cache_too_small: %s.", cache_too_small ? "true" : "false"); + NRF_LOG_DEBUG("keep_firmware: %s.", keep_firmware ? "true" : "false"); + NRF_LOG_DEBUG("delete_more: %s.", delete_more ? "true" : "false"); + + if (!delete_more || keep_firmware || (pass >= SOFTDEVICE_DELETED)) + { + // Stop, done. + break; + } + } + + if (cache_too_small) + { + NRF_LOG_WARNING("Aborting. Cannot fit new firmware on device"); + err_code = NRF_ERROR_NO_MEM; + } + else + { + // Room was found. Make the necessary preparations for receiving update. + +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) + if (pass >= SOFTDEVICE_DELETED) + { + NRF_LOG_DEBUG("Invalidating SoftDevice."); + nrf_dfu_softdevice_invalidate(); + } +#endif + if (pass >= APP_DELETED_DELETE_SOFTDEVICE) + { + NRF_LOG_DEBUG("Invalidating app."); + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + err_code = NRF_SUCCESS; + } + + return err_code; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h new file mode 100644 index 000000000..0a5c552f5 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_utils.h @@ -0,0 +1,154 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup sdk_nrf_dfu_utils DFU utilities + * @{ + * @ingroup nrf_dfu + */ + +#ifndef NRF_DFU_UTILS_H__ +#define NRF_DFU_UTILS_H__ + +#include +#include +#include "nrf_dfu_types.h" +#include "app_util.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * Round up val to the next page boundary + */ +#define ALIGN_TO_PAGE(val) ALIGN_NUM((CODE_PAGE_SIZE), (val)) + + +/** @brief Function for getting the start address of bank 0. + * + * @note Bank 0 starts after the SoftDevice if a SoftDevice is present. + * + * @return The start address of bank 0. + */ +uint32_t nrf_dfu_bank0_start_addr(void); + + +/** @brief Function for getting the start address of bank 1. + * + * @return The start address of bank 1. + */ +uint32_t nrf_dfu_bank1_start_addr(void); + + +/** @brief Function for getting the start address of the app. + * + * @return The start address of the bootable app. + */ +uint32_t nrf_dfu_app_start_address(void); + + +/** @brief Function for getting the start address of the SoftDevice. + * + * @return The start address of the SoftDevivce. + */ +uint32_t nrf_dfu_softdevice_start_address(void); + + +/** @brief Function for finding and preparing a place in flash in which to store a DFU update. + * + * @details This function checks the size requirements and selects a location for + * placing the cache of the DFU images. + * The function tries to find enough space after the existing firmwares. If there is not + * enough space, the present application is deleted. If there is still not enough space, + * the SoftDevice is deleted. + * If @p single_bank is true, the default behavior is to immediately delete the app and + * SoftDevice as necessary to place the new firmware at its intended location. If the + * intended location cannot be made available, or if the update is a bootloader update, + * the update will be a dual bank update, and nothing will be deleted by this function + * except when needed for size. + * If @p keep_app is true, the app is never deleted by this function. Likewise if @p + * keep_softdevice is true, the SoftDevice is never deleted by this function. + * If the new firmware cannot fit within the constraints, nothing is deleted and the + * function fails. + * + * @param[in] required_size Requirements for the size of the new image. + * @param[in] single_bank Whether to put the firmware directly where it's meant to go. + * @p keep_app and @p keep_softdevice take precedence over this. + * @param[in] keep_app True to ensure the app is not deleted by this function. This + * effectively enforces dual bank update. + * @param[out] keep_softdevice True to ensure the SoftDevice is not deleted by this function. + * + * @retval NRF_SUCCESS If a cache location was found for the DFU process. + * @retval NRF_ERROR_NO_MEM If there is not enough space available to receive the update. + * Nothing has been deleted. + */ +uint32_t nrf_dfu_cache_prepare(uint32_t required_size, bool single_bank, bool keep_app, bool keep_softdevice); + + +/**@brief Function for making sure a SoftDevice is not recognized as such anymore. + * + * @details It works by overwriting the magic number of the SoftDevice with 0s. The + * magic number is used throughout the bootloader to detect whether a SoftDevice + * is present. + * + * @warning This function should only be called when both banks are already invalid. + * because the (implicit) position of the banks will shift when the SoftDevice + * is invalidated. + */ +void nrf_dfu_softdevice_invalidate(void); + + +/**@brief Function for making sure a bank is not copied or booted. + * + * @details This also sets the size of the bank to 0. + * + * @param[in] p_bank Pointer to the bank to be invalidated. + */ +void nrf_dfu_bank_invalidate(nrf_dfu_bank_t * const p_bank); + +#ifdef __cplusplus +} +#endif + +#endif // NRF_DFU_UTILS_H__ + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_validation.c b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.c new file mode 100644 index 000000000..e4e722a55 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.c @@ -0,0 +1,986 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_flash.h" +#include "nrf_bootloader_info.h" +#include "pb.h" +#include "pb_common.h" +#include "pb_decode.h" +#include "dfu-cc.pb.h" +#include "crc32.h" +#include "nrf_assert.h" +#include "nrf_dfu_validation.h" +#include "nrf_dfu_ver_validation.h" +#include "nrf_strerror.h" + +#include "blake2s.h" +#include "ed25519-donna/ed25519.h" +#include "secbool.h" + + +#define NRF_LOG_MODULE_NAME nrf_dfu_validation +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +NRF_LOG_MODULE_REGISTER(); + +#ifndef DFU_REQUIRES_SOFTDEVICE +#if !defined(BLE_STACK_SUPPORT_REQD) && !defined(ANT_STACK_SUPPORT_REQD) +#define DFU_REQUIRES_SOFTDEVICE 0 +#else +#define DFU_REQUIRES_SOFTDEVICE 1 +#endif +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +/* Whether a complete init command has been received and prevalidated, but the firmware + * is not yet fully transferred. This value will also be correct after reset. + */ +static bool m_valid_init_cmd_present = false; +static dfu_Packet m_packet = dfu_Packet_init_default; +static uint8_t* m_init_packet_data_ptr = 0; +static uint32_t m_init_packet_data_len = 0; +static pb_istream_t m_pb_stream; + +static dfu_InitCommand const * mp_init = NULL; + +extern const uint8_t NRF_BOOTLOADER_KEY_M; +extern const uint8_t NRF_BOOTLOADER_KEY_N; +extern const uint8_t * const NRF_BOOTLOADER_KEYS[]; + + +/** @brief Flag used by parser code to indicate that the init command has been found to be invalid. + */ +static bool m_init_packet_valid = false; +// +//static void pb_decoding_callback(pb_istream_t *str, +// uint32_t tag, +// pb_wire_type_t wire_type, +// void *iter) +//{ +// pb_field_iter_t* p_iter = (pb_field_iter_t *) iter; +// +// // Match the beginning of the init command. +// if (p_iter->pos->ptr == &dfu_init_command_fields[0]) +// { +// uint8_t * ptr = (uint8_t *)str->state; +// uint32_t size = str->bytes_left; +// +// if (m_init_packet_data_ptr != NULL || m_init_packet_data_len != 0) +// { +// m_init_packet_valid = false; +// return; +// } +// +// // Remove tag. +// while (*ptr & 0x80) +// { +// ptr++; +// size--; +// } +// ptr++; +// size--; +// +// // Store the info in init_packet_data. +// m_init_packet_data_ptr = ptr; +// m_init_packet_data_len = size; +// m_init_packet_valid = true; +// +// NRF_LOG_DEBUG("PB: Init packet data len: %d", size); +// } +//} + +/** @brief Function for decoding byte stream into variable. + * + * @retval true If the stored init command was successfully decoded. + * @retval false If there was no stored init command, or the decoding failed. + */ +static bool stored_init_cmd_decode(void) +{ + m_pb_stream = pb_istream_from_buffer(s_dfu_settings.init_command, + s_dfu_settings.progress.command_size); + + dfu_InitCommand * p_init; + + // Attach our callback to follow the field decoding. + //m_pb_stream.decoding_callback = pb_decoding_callback; + + m_init_packet_valid = false; + m_init_packet_data_ptr = NULL; + m_init_packet_data_len = 0; + memset(&m_packet, 0, sizeof(m_packet)); + + if (!pb_decode(&m_pb_stream, dfu_Packet_fields, &m_packet)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream"); + return false; + } + + if (m_packet.has_signed_command && m_packet.has_command) + { + NRF_LOG_ERROR("Handler: Invalid init command."); + return false; + } + + if (m_packet.has_signed_command) { + //TODO: this is where signed init command is stored, but is it guaranteed to be there always? + // pb_decoding_callback was meant to find it, how to do that without nanopb modifications? + m_init_packet_data_ptr = &s_dfu_settings.init_command[11]; + m_init_packet_data_len = s_dfu_settings.progress.command_size-(64+4+11); // signature, sigmask + m_init_packet_valid = true; + } + + if (!m_init_packet_valid || (m_packet.has_signed_command && m_packet.has_command)) + { + NRF_LOG_ERROR("Handler: Invalid init command."); + return false; + } + else if (m_packet.has_signed_command && m_packet.signed_command.command.has_init) + { + p_init = &m_packet.signed_command.command.init; + + m_pb_stream = pb_istream_from_buffer(m_init_packet_data_ptr, m_init_packet_data_len); + memset(p_init, 0, sizeof(dfu_InitCommand)); + + if (!pb_decode(&m_pb_stream, dfu_InitCommand_fields, p_init)) + { + NRF_LOG_ERROR("Handler: Invalid protocol buffer m_pb_stream (init command)"); + return false; + } + } + else if (m_packet.has_command && m_packet.command.has_init) + { + p_init = &m_packet.command.init; + } + else + { + return false; + } + + mp_init = p_init; + + return true; +} + +void nrf_dfu_validation_init(void) +{ + // If the command is stored to flash, init command was valid. + if ((s_dfu_settings.progress.command_size != 0) && + stored_init_cmd_decode()) + { + m_valid_init_cmd_present = true; + } + else + { + m_valid_init_cmd_present = false; + } +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (size == 0) + { + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else if (size > INIT_COMMAND_MAX_SIZE) + { + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + // Set DFU to uninitialized. + m_valid_init_cmd_present = false; + + // Reset all progress. + nrf_dfu_settings_progress_reset(); + + // Set the init command size. + s_dfu_settings.progress.command_size = size; + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if ((length + s_dfu_settings.progress.command_offset) > s_dfu_settings.progress.command_size) + { + NRF_LOG_ERROR("Init command larger than expected."); + ret_val = NRF_DFU_RES_CODE_INVALID_PARAMETER; + } + else + { + // Copy the received data to RAM, update offset and calculate CRC. + memcpy(&s_dfu_settings.init_command[s_dfu_settings.progress.command_offset], + p_data, + length); + + s_dfu_settings.progress.command_offset += length; + s_dfu_settings.progress.command_crc = crc32_compute(p_data, + length, + &s_dfu_settings.progress.command_crc); + } + return ret_val; +} + + +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size) +{ + *p_offset = s_dfu_settings.progress.command_offset; + *p_crc = s_dfu_settings.progress.command_crc; + *p_max_size = INIT_COMMAND_MAX_SIZE; +} + + +bool nrf_dfu_validation_init_cmd_present(void) +{ + return m_valid_init_cmd_present; +} + + +// Function determines if init command signature is obligatory. +static bool signature_required(dfu_FwType fw_type_to_be_updated) +{ + bool result = true; + + // DFU_FW_TYPE_EXTERNAL_APPLICATION and bootloader updates always require + // signature check + if ((!DFU_REQUIRES_SOFTDEVICE && (fw_type_to_be_updated == dfu_FwType_SOFTDEVICE)) || + (fw_type_to_be_updated == dfu_FwType_APPLICATION)) + { + result = NRF_DFU_REQUIRE_SIGNED_APP_UPDATE; + } + return result; +} + +static secbool compute_pubkey(uint8_t sig_m, uint8_t sig_n, + const uint8_t *const *pub, uint8_t sigmask, + ed25519_public_key res) { + if (0 == sig_m || 0 == sig_n) return secfalse; + if (sig_m > sig_n) return secfalse; + + // discard bits higher than sig_n + sigmask &= ((1 << sig_n) - 1); + + // remove if number of set bits in sigmask is not equal to sig_m + if (__builtin_popcount(sigmask) != sig_m) return secfalse; + + ed25519_public_key keys[sig_m]; + int j = 0; + for (int i = 0; i < sig_n; i++) { + if ((1 << i) & sigmask) { + memcpy(keys[j], pub[i], 32); + j++; + } + } + + return sectrue * (0 == ed25519_cosi_combine_publickeys(res, keys, sig_m)); +} + +secbool check_trezor_sig(const uint8_t * digest, + size_t digest_len, + uint8_t key_m, + uint8_t key_n, + uint8_t sigmask, + const uint8_t *const *keys, + uint8_t * sig) { + // check header signature + + + ed25519_public_key pub; + if (sectrue != compute_pubkey(key_m, key_n, keys, sigmask, pub)) + return secfalse; + + return sectrue * + (0 == ed25519_sign_open(digest, digest_len, pub, + sig)); +} + + +// Function to perform signature check if required. +static nrf_dfu_result_t nrf_dfu_validation_signature_check(uint32_t sigmask, + uint8_t const * p_signature, + uint32_t signature_len, + uint8_t const * p_data, + uint32_t data_len) +{ + ret_code_t err_code = NRF_SUCCESS; + + uint8_t hash_digest[BLAKE2S_DIGEST_LENGTH]; + uint8_t signature[64]; + + NRF_LOG_INFO("Signature required. Checking signature.") + if (p_signature == NULL) + { + NRF_LOG_WARNING("No signature found."); + return EXT_ERR(NRF_DFU_EXT_ERROR_SIGNATURE_MISSING); + } + + + NRF_LOG_INFO("Calculating hash (len: %d)", data_len); + + blake2s(p_data, data_len, hash_digest, BLAKE2S_DIGEST_LENGTH); + + + if (sizeof(signature) != signature_len) + { + return NRF_DFU_RES_CODE_OPERATION_FAILED; + } + + // Prepare the signature received over the air. + memcpy(signature, p_signature, signature_len); + + // Calculate the signature. + NRF_LOG_INFO("Verify signature"); + + if (sectrue != check_trezor_sig(hash_digest, BLAKE2S_DIGEST_LENGTH, NRF_BOOTLOADER_KEY_M, NRF_BOOTLOADER_KEY_N, sigmask, NRF_BOOTLOADER_KEYS, signature)){ + NRF_LOG_ERROR("Signature failed"); + err_code = NRF_DFU_ERROR_INVALID_SIGNATURE; + } + + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Signature failed (err_code: 0x%x)", err_code); + NRF_LOG_DEBUG("Signature:"); + NRF_LOG_HEXDUMP_DEBUG(signature, sizeof(signature)); + NRF_LOG_DEBUG("Hash:"); + NRF_LOG_HEXDUMP_DEBUG(hash_digest, BLAKE2S_DIGEST_LENGTH); + NRF_LOG_FLUSH(); + + return NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + NRF_LOG_INFO("Image verified"); + return NRF_DFU_RES_CODE_SUCCESS; +} + + +// Function to calculate the total size of the firmware(s) in the update. +static nrf_dfu_result_t update_data_size_get(dfu_InitCommand const * p_init, uint32_t * p_size) +{ + nrf_dfu_result_t ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + uint32_t fw_sz = 0; + + if ((p_init->type == dfu_FwType_APPLICATION || + p_init->type == dfu_FwType_EXTERNAL_APPLICATION) && + (p_init->has_app_size == true)) + { + fw_sz = p_init->app_size; + } + else + { + if ((p_init->type & dfu_FwType_SOFTDEVICE) && (p_init->has_sd_size == true)) + { + fw_sz = p_init->sd_size; + } + + if ((p_init->type & dfu_FwType_BOOTLOADER) && (p_init->has_bl_size == true)) + { + if (p_init->bl_size <= BOOTLOADER_SIZE) + { + fw_sz += p_init->bl_size; + } + else + { + NRF_LOG_ERROR("BL size (%d) over limit (%d)", p_init->bl_size, BOOTLOADER_SIZE); + fw_sz = 0; + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + } + } + + if (fw_sz) + { + *p_size = fw_sz; + ret_val = NRF_DFU_RES_CODE_SUCCESS; + } + else + { + NRF_LOG_ERROR("Init packet does not contain valid firmware size"); + } + + return ret_val; +} + + +/** + * @brief Function to check if single bank update should be used. + * + * @param new_fw_type Firmware type. + */ +static bool use_single_bank(dfu_FwType new_fw_type) +{ + bool result = false; + + // DFU_FW_TYPE_EXTERNAL_APPLICATION never uses single bank + if (((new_fw_type == dfu_FwType_APPLICATION) || + (new_fw_type == dfu_FwType_SOFTDEVICE)) && + NRF_DFU_SINGLE_BANK_APP_UPDATES) + { + result = true; + } + + return result; +} + + +// Function to determine whether the new firmware needs a SoftDevice to be present. +static bool update_requires_softdevice(dfu_InitCommand const * p_init) +{ + return ((p_init->sd_req_count > 0) && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)); +} + + +// Function to determine whether the SoftDevice can be removed during the update or not. +static bool keep_softdevice(dfu_InitCommand const * p_init) +{ + UNUSED_PARAMETER(p_init); // It's unused when DFU_REQUIRES_SOFTDEVICE is true. + return DFU_REQUIRES_SOFTDEVICE || update_requires_softdevice(p_init); +} + + +/**@brief Function to determine where to temporarily store the incoming firmware. + * This also checks whether the update will fit, and deletes existing + * firmware to make room for the new firmware. + * + * @param[in] p_init Init command. + * @param[in] fw_size The size of the incoming firmware. + * @param[out] p_addr The address at which to initially store the firmware. + * + * @retval NRF_DFU_RES_CODE_SUCCESS If the size check passed and + * an address was found. + * @retval NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES If the size check failed. + */ +static nrf_dfu_result_t update_data_addr_get(dfu_InitCommand const * p_init, + uint32_t fw_size, + uint32_t * p_addr) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + ret_code_t err_code = nrf_dfu_cache_prepare(fw_size, + use_single_bank(p_init->type), + NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES, + keep_softdevice(p_init)); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Can't find room for update"); + ret_val = NRF_DFU_RES_CODE_INSUFFICIENT_RESOURCES; + } + else + { + *p_addr = nrf_dfu_bank1_start_addr(); + NRF_LOG_DEBUG("Write address set to 0x%08x", *p_addr); + } + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_Command const * p_command = &m_packet.command; + uint32_t sigmask = 0; + uint8_t const * p_signature = NULL; + uint32_t signature_len = 0; + + if (m_packet.has_signed_command) + { + p_command = &m_packet.signed_command.command; + sigmask = m_packet.signed_command.sigmask; + p_signature = m_packet.signed_command.signature.bytes; + signature_len = m_packet.signed_command.signature.size; + } + + // Validate signature. + if (signature_required(p_command->init.type)) + { + ret_val = nrf_dfu_validation_signature_check(sigmask, + p_signature, + signature_len, + m_init_packet_data_ptr, + m_init_packet_data_len); + } + + // Validate versions. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = nrf_dfu_ver_validation_check(&p_command->init); + } + + if (ret_val != NRF_DFU_RES_CODE_SUCCESS) + { + NRF_LOG_WARNING("Prevalidation failed."); + NRF_LOG_DEBUG("Init command:"); + NRF_LOG_HEXDUMP_DEBUG(m_init_packet_data_ptr, m_init_packet_data_len); + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + + if (s_dfu_settings.progress.command_offset != s_dfu_settings.progress.command_size) + { + // The object wasn't the right (requested) size. + NRF_LOG_ERROR("Execute with faulty offset"); + ret_val = NRF_DFU_RES_CODE_OPERATION_NOT_PERMITTED; + } + else if (m_valid_init_cmd_present) + { + *p_dst_data_addr = nrf_dfu_bank1_start_addr(); + ret_val = update_data_size_get(mp_init, p_data_len); + } + else if (stored_init_cmd_decode()) + { + // Will only get here if init command was received since last reset. + // An init command should not be written to flash until after it's been checked here. + ret_val = nrf_dfu_validation_prevalidate(); + + *p_dst_data_addr = 0; + *p_data_len = 0; + + // Get size of binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_size_get(mp_init, p_data_len); + } + + // Get address where to flash the binary. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + ret_val = update_data_addr_get(mp_init, *p_data_len, p_dst_data_addr); + } + + // Set flag validating the init command. + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + m_valid_init_cmd_present = true; + } + else + { + nrf_dfu_settings_progress_reset(); + } + } + else + { + NRF_LOG_ERROR("Failed to decode init packet"); + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + + return ret_val; +} + + +// Function to check the hash received in the init command against the received firmware. +// little_endian specifies the endianness of @p p_hash. +static bool nrf_dfu_validation_hash_ok(uint8_t const * p_hash, uint32_t src_addr, uint32_t data_len) +{ + bool result = true; + uint8_t hash[BLAKE2S_DIGEST_LENGTH]; + + + NRF_LOG_DEBUG("Hash verification. start address: 0x%x, size: 0x%x", + src_addr, + data_len); + + blake2s( (uint8_t*)src_addr, data_len, hash, BLAKE2S_DIGEST_LENGTH); + + if (memcmp(hash, p_hash, BLAKE2S_DIGEST_LENGTH) != 0) + { + NRF_LOG_WARNING("Hash verification failed."); + NRF_LOG_DEBUG("Expected FW hash:") + NRF_LOG_HEXDUMP_DEBUG(p_hash, BLAKE2S_DIGEST_LENGTH); + NRF_LOG_DEBUG("Actual FW hash:") + NRF_LOG_HEXDUMP_DEBUG(hash, BLAKE2S_DIGEST_LENGTH); + NRF_LOG_FLUSH(); + + result = false; + } + + return result; +} + + +// Function to check the hash received in the init command against the received firmware. +bool fw_hash_ok(dfu_InitCommand const * p_init, uint32_t fw_start_addr, uint32_t fw_size) +{ + ASSERT(p_init != NULL); + return nrf_dfu_validation_hash_ok((uint8_t *)p_init->hash.hash.bytes, fw_start_addr, fw_size); +} + + +// Function to check whether the update contains a SoftDevice and, if so, if it is of a different +// major version than the existing SoftDevice. +static bool is_major_softdevice_update(uint32_t new_sd_addr) +{ + // True if there is no SD right now, but there is a new one coming. This counts as a major update. + bool result = !SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER); + + if (SD_PRESENT && (SD_MAGIC_NUMBER_GET(new_sd_addr) == SD_MAGIC_NUMBER)) + { + // Both SoftDevices are present. + uint32_t current_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(MBR_SIZE)); + uint32_t new_SD_major = SD_MAJOR_VERSION_EXTRACT(SD_VERSION_GET(new_sd_addr)); + + result = (current_SD_major != new_SD_major); + + NRF_LOG_INFO("SoftDevice update is a %s version update. Current: %d. New: %d.", + result ? "major" : "minor", + current_SD_major, + new_SD_major); + } + + return result; +} + + +/**@brief Validate the SoftDevice size and magic number in structure found at 0x2000 in received SoftDevice. + * + * @param[in] sd_start_addr Start address of received SoftDevice. + * @param[in] sd_size Size of received SoftDevice in bytes. + */ +static bool softdevice_info_ok(uint32_t sd_start_addr, uint32_t sd_size) +{ + bool result = true; + + if (SD_MAGIC_NUMBER_GET(sd_start_addr) != SD_MAGIC_NUMBER) + { + NRF_LOG_ERROR("The SoftDevice does not contain the magic number identifying it as a SoftDevice."); + result = false; + } + else if (SD_SIZE_GET(sd_start_addr) < ALIGN_TO_PAGE(sd_size + MBR_SIZE)) + { + // The size in the info struct should be rounded up to a page boundary + // and be larger than the actual size + the size of the MBR. + NRF_LOG_ERROR("The SoftDevice size in the info struct is too small compared with the size reported in the init command."); + result = false; + } + else if (SD_PRESENT && (SD_ID_GET(MBR_SIZE) != SD_ID_GET(sd_start_addr))) + { + NRF_LOG_ERROR("The new SoftDevice is of a different family than the present SoftDevice. Compatibility cannot be guaranteed."); + result = false; + } + + return result; +} + + +static bool boot_validation_extract(boot_validation_t * p_boot_validation, + dfu_InitCommand const * p_init, + uint32_t index, + uint32_t start_addr, + uint32_t data_len, + boot_validation_type_t default_type) +{ + memset(p_boot_validation, 0, sizeof(boot_validation_t)); + p_boot_validation->sigmask = (boot_validation_type_t)p_init->boot_validation[index].sigmask; + + memcpy(p_boot_validation->bytes, p_init->boot_validation[index].bytes.bytes, p_init->boot_validation[index].bytes.size); + + if (default_type == NO_VALIDATION) { + return true; + } + + return nrf_dfu_validation_boot_validate(p_boot_validation, start_addr, data_len); +} + + +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_app(dfu_InitCommand const * p_init, uint32_t src_addr, uint32_t data_len, bool is_trusted) +{ + boot_validation_t boot_validation; + + ASSERT(p_init->type == dfu_FwType_APPLICATION); + + if (!boot_validation_extract(&boot_validation, p_init, 0, src_addr, data_len, VALIDATE_ECDSA_P256_SHA256)) + { + return false; + } +//#if !NRF_DFU_IN_APP +// else if (NRF_BL_APP_SIGNATURE_CHECK_REQUIRED && +// (boot_validation.type != VALIDATE_ECDSA_P256_SHA256)) +// { +// NRF_LOG_WARNING("The boot validation of the app must be a signature check."); +// return false; +// } +//#endif + + if (!is_trusted) + { + return true; + } + + memcpy(&s_dfu_settings.boot_validation_app, &boot_validation, sizeof(boot_validation)); + + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_APP; + + NRF_LOG_DEBUG("Invalidating old application in bank 0."); + s_dfu_settings.bank_0.bank_code = NRF_DFU_BANK_INVALID; + + if (!DFU_REQUIRES_SOFTDEVICE && !update_requires_softdevice(p_init)) + { + // App does not need SD, so it should be placed where SD is. + nrf_dfu_softdevice_invalidate(); + } + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + s_dfu_settings.app_version = p_init->fw_version; + } + + return true; +} + + +// Function to check a received SoftDevice or Bootloader firmware, or both, +// before it is copied into place. +// The is_trusted argument specifies whether the function should have side effects. +static bool postvalidate_sd_bl(dfu_InitCommand const * p_init, + bool with_sd, + bool with_bl, + uint32_t start_addr, + uint32_t data_len, + bool is_trusted) +{ + boot_validation_t boot_validation_sd = {NO_VALIDATION}; + boot_validation_t boot_validation_bl = {NO_VALIDATION}; + uint32_t bl_start = start_addr; + uint32_t bl_size = data_len; + + ASSERT(with_sd || with_bl); + + if (with_sd) + { + if (!softdevice_info_ok(start_addr, p_init->sd_size)) + { + return false; + } + + if (is_major_softdevice_update(start_addr)) + { + NRF_LOG_WARNING("Invalidating app because it is incompatible with the SoftDevice."); + if (DFU_REQUIRES_SOFTDEVICE && !with_bl) + { + NRF_LOG_ERROR("Major SD update but no BL. Abort to avoid incapacitating the BL."); + return false; + } + } + + if (!boot_validation_extract(&boot_validation_sd, p_init, 0, start_addr, p_init->sd_size, VALIDATE_ECDSA_P256_SHA256)) + { + return false; + } + + bl_start += p_init->sd_size; + bl_size -= p_init->sd_size; + } + if (with_bl) + { + boot_validation_extract(&boot_validation_bl, p_init, with_sd ? 1 : 0, bl_start, bl_size, NO_VALIDATION); + } + + if (!is_trusted) + { + return true; + } + + if (with_sd) + { + if (is_major_softdevice_update(start_addr)) + { + // Invalidate app since it may not be compatible with new SD. + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_0); + } + + memcpy(&s_dfu_settings.boot_validation_softdevice, &boot_validation_sd, sizeof(boot_validation_sd)); + + // Mark the update as valid. + s_dfu_settings.bank_1.bank_code = with_bl ? NRF_DFU_BANK_VALID_SD_BL + : NRF_DFU_BANK_VALID_SD; + + s_dfu_settings.sd_size = p_init->sd_size; + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_BL; + } + + + if (with_bl) + { + memcpy(&s_dfu_settings.boot_validation_bootloader, &boot_validation_bl, sizeof(boot_validation_bl)); + + if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && (p_init->has_is_debug == false || p_init->is_debug == false))) + { + // If the update contains a bootloader, update the version. + // Unless the update is a debug packet. + s_dfu_settings.bootloader_version = p_init->fw_version; + } + } + + return true; +} + + +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len) +{ + uint8_t const * p_data = (uint8_t*) data_addr; + + nrf_dfu_result_t res_code = nrf_dfu_validation_signature_check( + p_validation->sigmask, + p_validation->bytes, + 64, + p_data, + data_len); + return (res_code == NRF_DFU_RES_CODE_SUCCESS); + +} + + +nrf_dfu_result_t postvalidate(uint32_t data_addr, uint32_t data_len, bool is_trusted) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + dfu_InitCommand const * p_init = mp_init; + + if (!fw_hash_ok(p_init, data_addr, data_len)) + { + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_VERIFICATION_FAILED); + } + else + { + if (p_init->type == dfu_FwType_APPLICATION) + { + if (!postvalidate_app(p_init, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + if (!is_trusted) + { + // This function must be implemented externally + ret_val = nrf_dfu_validation_post_external_app_execute(p_init, is_trusted); + } + else + { + s_dfu_settings.bank_1.bank_code = NRF_DFU_BANK_VALID_EXT_APP; + } + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + bool with_sd = p_init->type & dfu_FwType_SOFTDEVICE; + bool with_bl = p_init->type & dfu_FwType_BOOTLOADER; + + if (!postvalidate_sd_bl(p_init, with_sd, with_bl, data_addr, data_len, is_trusted)) + { + ret_val = NRF_DFU_RES_CODE_INVALID_OBJECT; + if (is_trusted && with_sd && !DFU_REQUIRES_SOFTDEVICE && + (data_addr == nrf_dfu_softdevice_start_address())) + { + nrf_dfu_softdevice_invalidate(); + } + } + } + } + + if (!is_trusted) + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_1; + } + else + { + nrf_dfu_settings_progress_reset(); + } + } + else + { + if (ret_val == NRF_DFU_RES_CODE_SUCCESS) + { + // Mark the update as complete and valid. + s_dfu_settings.bank_1.image_crc = crc32_compute((uint8_t *)data_addr, data_len, NULL); + s_dfu_settings.bank_1.image_size = data_len; + } + else + { + nrf_dfu_bank_invalidate(&s_dfu_settings.bank_1); + } + + nrf_dfu_settings_progress_reset(); + s_dfu_settings.progress.update_start_address = data_addr; + } + + return ret_val; +} + + +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, false); +} + + +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len) +{ + return postvalidate(data_addr, data_len, true); +} + + +bool nrf_dfu_validation_valid_external_app(void) +{ + return s_dfu_settings.bank_1.bank_code == NRF_DFU_BANK_VALID_EXT_APP; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h new file mode 100644 index 000000000..79fdbc52a --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_validation.h @@ -0,0 +1,199 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/**@file + * + * @defgroup nrf_dfu_validation Validation + * @{ + * @ingroup nrf_dfu + */ + +#ifndef __NRF_DFU_VALIDATION_H +#define __NRF_DFU_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_handling_error.h" + +/** + * @brief Function for module initialization. + * + * Function checks if there is a valid init packet in DFU settings written in flash. + */ +void nrf_dfu_validation_init(void); + +/** + * @brief Function called on reception of init command creation request. + * + * @param[in] size Size of incoming init packet. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_create(uint32_t size); + +/** + * @brief Function called on reception of fragment of init command. + * + * @param[in] p_data Init command fragment. + * @param[in] length Init command fragment size. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_append(uint8_t const * p_data, uint32_t length); + +/** + * @brief Function for getting init command status. + * + * @param[out] p_offset Current offset. + * @param[out] p_crc Current CRC. + * @param[out] p_max_size Maximum size of init command. + */ +void nrf_dfu_validation_init_cmd_status_get(uint32_t * p_offset, + uint32_t * p_crc, + uint32_t * p_max_size); + +/** + * @brief Function for inquiring whether a valid init command has been received. + * + * @return true if there is a valid init command. This can be true at boot time + * if the device was reset during a DFU operation. + */ +bool nrf_dfu_validation_init_cmd_present(void); + +/** + * @brief Function for validating init command and retrieving the address and length of the firmware. + * + * If init command is successfully validated Bank 1 details are written to out parameters. + * + * Until @ref nrf_dfu_validation_init_cmd_create is called, this function can be called + * again after the first time without side effects to retrieve address and length. + * + * @param[out] p_dst_data_addr Start address of received data, if validation is successful. + * @param[out] p_data_len Expected length of received data, if validation is successful. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_init_cmd_execute(uint32_t * p_dst_data_addr, + uint32_t * p_data_len); + +/** + * @brief Function for validating the init command. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_prevalidate(void); + +/** + * @brief Function for validating the firmware for booting. + * + * @param[in] p_validation Validation parameters. + * @param[in] data_addr Start address of the firmware. + * @param[in] data_len Length of the firmware. + * + * @return Whether the firmware is valid for booting. + */ +bool nrf_dfu_validation_boot_validate(boot_validation_t const * p_validation, uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for postvalidating the update after all data is received. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_data_execute(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function for preparing the update for activation. + * + * This function is called after a reset, after all data is received. This function also runs + * @ref nrf_dfu_validation_post_data_execute internally. If this succeeds, the update is + * activated by the activation machinery in the bootloader the next time it runs. + * + * @note The caller must have permissions to edit the relevant entries in the settings. + * + * @param[in] data_addr Start address of the received data. + * @param[in] data_len Length of the received data. + * + * @return Operation result. See @ref nrf_dfu_result_t + */ +nrf_dfu_result_t nrf_dfu_validation_activation_prepare(uint32_t data_addr, uint32_t data_len); + +/** + * @brief Function to execute on a validated external app. + * + * @details This function is called once all data is received with the parameter + * @p is_boot set to false. The function is called during bootup with the parameter + * set to true. + * + * + * + * @note This function requires that @ref NRF_DFU_SUPPORTS_EXTERNAL_APP is set to 1. + * It is up to the user to implement this function. + * + * @warning Parameter @p is_trusted must be used to ensure that no loss of security of process can happen. + * This parameter should only be set if the function is called after a root-of-trust + * reset on the device. + * + * Parameter @p is_trusted can be used for the following: + * - Ensuring that an external application is run only once (after root-of-trust). + * - Ensuring that a bank flag or any other flash access can only happen after root-of-trust. + * - Ensuring that the device reaches the correct state after a power failure on the device. + * + * @param[in] p_init Init command for the firmware upgrade. + * @param[in] is_trusted Must be set to true if this is called after root-of-trust boot. + * Must be set to false if this is called from DFU mode or background + * DFU operation. + * + * @return Operation result. see @ref nrf_dfu_result_t. + */ +nrf_dfu_result_t nrf_dfu_validation_post_external_app_execute(dfu_InitCommand const * p_init, bool is_trusted); + +/** +* @brief Function to check if there is a valid external app in Bank 1. +* +* @returns True if valid external app, otherwise false. +*/ +bool nrf_dfu_validation_valid_external_app(void); + +#endif //__NRF_DFU_VALIDATION_H + +/** @} */ diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c new file mode 100644 index 000000000..3d811a2e2 --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.c @@ -0,0 +1,311 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include +#include "nrf_dfu_types.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_bootloader_info.h" +#include "nrf_assert.h" +#include "dfu-cc.pb.h" +#include "nrf_dfu_ver_validation.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_ver_validation +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +/** @brief Macro for reading the Firmware ID of a SoftDevice at a given base address. + */ +#ifndef _SD_FWID_GET +#define _SD_FWID_GET(baseaddr) SD_OFFSET_GET_UINT16(baseaddr, 0x0C) +#endif + +#define EXT_ERR(err) (nrf_dfu_result_t)((uint32_t)NRF_DFU_RES_CODE_EXT_ERROR + (uint32_t)err) + +static bool sd_req_check(uint32_t const * p_sd_req, uint8_t sd_req_cnt, bool accept_any) +{ + bool result = false; + for (uint8_t i = 0; i < sd_req_cnt; i++) + { + if ((SD_PRESENT && (p_sd_req[i] == _SD_FWID_GET(MBR_SIZE))) || + (accept_any && (p_sd_req[i] == SD_REQ_ANY_VERSION)) + ) + { + // Found a matching sd_req field. sd_req is ok. + result = true; + break; + } + } + return result; +} + + +static bool sd_req_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + bool result; +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + // The bootloader needs the SoftDevice, so disabling NRF_DFU_APP_DOWNGRADE_PREVENTION + // should not be applied to SoftDevice updates. + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION || (p_init->type == DFU_FW_TYPE_SOFTDEVICE); +#else + const bool prevent_downgrade = NRF_DFU_APP_DOWNGRADE_PREVENTION; +#endif + + if (SD_PRESENT) + { + if (p_init->sd_req_count == 0) + { + result = false; + } + else if (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD) + { + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == dfu_FwType_EXTERNAL_APPLICATION)); + } + else if (p_init->type == dfu_FwType_APPLICATION) + { + // The application wants to overwrite the SoftDevice. + if (prevent_downgrade && (p_init->sd_req_count > 1) && (p_init->sd_req[0] == SD_REQ_APP_OVERWRITES_SD)) + { + // The application can overwrite the SD if sd_req[0] == 0 and table has the FWID of the current SD. + result = sd_req_check(p_init->sd_req, p_init->sd_req_count, false); + + // Prevent BLE/ANT bootloaders from allowing applications overwriting the SoftDevice. +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + result = false; +#endif + } + else + { + result = true; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + // Won't accept FW upgrade using external application to + // enforce replacing SoftDevice (SD_REQ_APP_OVERWRITES_SD) + result = false; + } +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + // Don't allow SoftDevice updates which assume no SD is present already. + result = !prevent_downgrade || (p_init->type != dfu_FwType_SOFTDEVICE); + } + } + + else + { + if (p_init->sd_req_count && (p_init->sd_req[0] != SD_REQ_APP_OVERWRITES_SD)) + { + // Fail if there is no SD and the update requires SD. The special "any" FWID is valid + // for external apps only. + result = false; +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + result = sd_req_check(p_init->sd_req, + p_init->sd_req_count, + (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION)); +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + } + else + { + // If there is no SD and update has SD it is accepted only if it has a fw_version. + result = !prevent_downgrade || p_init->has_fw_version; + } + } + return result; +} + + +static bool fw_hash_type_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + + return (p_init->hash.hash_type == dfu_HashType_SHA256); +} + + +static bool fw_version_required(dfu_FwType new_fw_type) +{ + bool result = true; + + if (new_fw_type == dfu_FwType_SOFTDEVICE) + { + result = false; // fw_version is optional in SoftDevice updates. If present, it will be checked against the app version. + } + else if (new_fw_type == dfu_FwType_APPLICATION) + { + result = NRF_DFU_APP_DOWNGRADE_PREVENTION; // fw_version is configurable in app updates. + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if !NRF_DFU_EXTERNAL_APP_VERSIONING + else if (new_fw_type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return false; + } +#endif //!NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + + return result; +} + + +static bool fw_type_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + + return ((p_init->has_type) + && ( (p_init->type == dfu_FwType_APPLICATION) + || (p_init->type == dfu_FwType_SOFTDEVICE) + || (p_init->type == dfu_FwType_BOOTLOADER) + || (p_init->type == dfu_FwType_SOFTDEVICE_BOOTLOADER) +#if NRF_DFU_SUPPORTS_EXTERNAL_APP + || (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + )); + +} + + +#ifndef NRF_DFU_APP_ACCEPT_SAME_VERSION +#define NRF_DFU_APP_ACCEPT_SAME_VERSION 1 +#endif + + +// This function assumes p_init->has_fw_version. +static bool fw_version_ok(dfu_InitCommand const * p_init) +{ + ASSERT(p_init != NULL); + ASSERT(p_init->has_fw_version); + + if ((p_init->type == dfu_FwType_APPLICATION) || + (p_init->type == dfu_FwType_SOFTDEVICE)) + { + if (!NRF_DFU_APP_DOWNGRADE_PREVENTION) + { + return true; + } + else if ((p_init->fw_version > s_dfu_settings.app_version)) + { + return true; + } + else if ((p_init->fw_version == s_dfu_settings.app_version)) + { + return NRF_DFU_APP_ACCEPT_SAME_VERSION; + } + else + { + return false; + } + } +#if NRF_DFU_SUPPORTS_EXTERNAL_APP +#if NRF_DFU_EXTERNAL_APP_VERSIONING + else if (p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return (p_init->fw_version >= s_dfu_settings.app_version); + } +#else + else if(p_init->type == DFU_FW_TYPE_EXTERNAL_APPLICATION) + { + return true; + } +#endif // NRF_DFU_EXTERNAL_APP_VERSIONING +#endif // NRF_DFU_SUPPORTS_EXTERNAL_APP + else + { + return (p_init->fw_version > s_dfu_settings.bootloader_version); + } +} + + +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init) +{ + nrf_dfu_result_t ret_val = NRF_DFU_RES_CODE_SUCCESS; + if (!fw_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid firmware type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (!fw_hash_type_ok(p_init)) + { + NRF_LOG_ERROR("Invalid hash type."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_WRONG_HASH_TYPE); + } + else if (!NRF_DFU_DEBUG || + (NRF_DFU_DEBUG && ((p_init->has_is_debug == false) || (p_init->is_debug == false)))) + { + if (p_init->has_hw_version == false) + { + NRF_LOG_ERROR("No HW version."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + else if (p_init->hw_version != NRF_DFU_HW_VERSION) + { + NRF_LOG_WARNING("Faulty HW version."); + ret_val = EXT_ERR( NRF_DFU_EXT_ERROR_HW_VERSION_FAILURE); + } + + else if (!sd_req_ok(p_init)) + { + NRF_LOG_WARNING("SD req not met."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_SD_VERSION_FAILURE); + } + else if (p_init->has_fw_version) + { + if (!fw_version_ok(p_init)) + { + NRF_LOG_WARNING("FW version too low."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_FW_VERSION_FAILURE); + } + } + else + { + if (fw_version_required(p_init->type)) + { + NRF_LOG_ERROR("FW version missing."); + ret_val = EXT_ERR(NRF_DFU_EXT_ERROR_INIT_COMMAND_INVALID); + } + } + } + return ret_val; +} diff --git a/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h new file mode 100644 index 000000000..d17d5f02f --- /dev/null +++ b/core/embed/ble_bootloader/dfu/nrf_dfu_ver_validation.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __NRF_DFU_VER_VALIDATION_H +#define __NRF_DFU_VER_VALIDATION_H + +#include "stdint.h" +#include "sdk_errors.h" +#include "nrf_dfu_handling_error.h" +#include "dfu-cc.pb.h" + +/** @brief SD_REQ field value which indicates that Softdevice can be overwritten by the application. */ +#define SD_REQ_APP_OVERWRITES_SD 0 + +/** @brief SD_REQ_ANY_VERSION field value which indicates that any SoftDevice version is valid. + * + * @note This is used by external application in case SoftDevice version compatibility isn't needed. + */ +#define SD_REQ_ANY_VERSION (0xFFFE) + +/** + * @brief Function for validating version of new firmware. + * + * @return NRF_DFU_RES_CODE_SUCCESS if successful or error code otherwise + */ +nrf_dfu_result_t nrf_dfu_ver_validation_check(dfu_InitCommand const * p_init); + +#endif //__NRF_DFU_VER_VALIDATION_H diff --git a/core/embed/ble_bootloader/dfu_public_key.c b/core/embed/ble_bootloader/dfu_public_key.c new file mode 100644 index 000000000..9d22b9bf0 --- /dev/null +++ b/core/embed/ble_bootloader/dfu_public_key.c @@ -0,0 +1,20 @@ + +/* This file was automatically generated by nrfutil on 2023-01-23 (YY-MM-DD) at + * 16:58:55 */ + +#include "compiler_abstraction.h" +#include "stdint.h" + +/** @brief Public keys used to verify DFU images */ + +const uint8_t NRF_BOOTLOADER_KEY_M = 2; +const uint8_t NRF_BOOTLOADER_KEY_N = 3; +const uint8_t * const NRF_BOOTLOADER_KEYS[] = { +#if !PRODUCTION + (const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d", + (const uint8_t *)"\x21\x52\xf8\xd1\x9b\x79\x1d\x24\x45\x32\x42\xe1\x5f\x2e\xab\x6c\xb7\xcf\xfa\x7b\x6a\x5e\xd3\x00\x97\x96\x0e\x06\x98\x81\xdb\x12", + (const uint8_t *)"\x22\xfc\x29\x77\x92\xf0\xb6\xff\xc0\xbf\xcf\xdb\x7e\xdb\x0c\x0a\xa1\x4e\x02\x5a\x36\x5e\xc0\xe3\x42\xe8\x6e\x38\x29\xcb\x74\xb6", +#else + MODEL_NRF_BOOTLOADER_KEYS +#endif +}; diff --git a/core/embed/ble_bootloader/jlink.jdebug b/core/embed/ble_bootloader/jlink.jdebug new file mode 100644 index 000000000..a29b4a790 --- /dev/null +++ b/core/embed/ble_bootloader/jlink.jdebug @@ -0,0 +1,332 @@ +/********************************************************************* +* (c) SEGGER Microcontroller GmbH * +* The Embedded Experts * +* www.segger.com * +********************************************************************** + +File : /home/mbruna/CLionProjects/trezor-model_r/core/embed/ble_bootloader/jlink.jdebug +Created : 6 Feb 2023 15:54 +Ozone Version : V3.28c +*/ + +/********************************************************************* +* +* OnProjectLoad +* +* Function description +* Project load routine. Required. +* +********************************************************************** +*/ +void OnProjectLoad (void) { + // + // Dialog-generated settings + // + Project.AddPathSubstitute (".", "$(ProjectDir)"); + Project.AddPathSubstitute (".", "$(ProjectDir)"); + Project.SetDevice ("Cortex-M4"); + Project.SetHostIF ("USB", ""); + Project.SetTargetIF ("SWD"); + Project.SetTIFSpeed ("20 MHz"); + Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd"); + // + // User settings + // + File.Open ("../../build/ble_bootloader/ble_bootloader.elf"); +} + +/********************************************************************* +* +* OnStartupComplete +* +* Function description +* Called when program execution has reached/passed +* the startup completion point. Optional. +* +********************************************************************** +*/ +//void OnStartupComplete (void) { +//} + +/********************************************************************* +* +* TargetReset +* +* Function description +* Replaces the default target device reset routine. Optional. +* +* Notes +* This example demonstrates the usage when +* debugging an application in RAM on a Cortex-M target device. +* +********************************************************************** +*/ +//void TargetReset (void) { +// +// unsigned int SP; +// unsigned int PC; +// unsigned int VectorTableAddr; +// +// VectorTableAddr = Elf.GetBaseAddr(); +// // +// // Set up initial stack pointer +// // +// if (VectorTableAddr != 0xFFFFFFFF) { +// SP = Target.ReadU32(VectorTableAddr); +// Target.SetReg("SP", SP); +// } +// // +// // Set up entry point PC +// // +// PC = Elf.GetEntryPointPC(); +// +// if (PC != 0xFFFFFFFF) { +// Target.SetReg("PC", PC); +// } else if (VectorTableAddr != 0xFFFFFFFF) { +// PC = Target.ReadU32(VectorTableAddr + 4); +// Target.SetReg("PC", PC); +// } else { +// Util.Error("Project file error: failed to set entry point PC", 1); +// } +//} + +/********************************************************************* +* +* BeforeTargetReset +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetReset (void) { +//} + +/********************************************************************* +* +* AfterTargetReset +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +** +********************************************************************** +*/ +void AfterTargetReset (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* DebugStart +* +* Function description +* Replaces the default debug session startup routine. Optional. +* +********************************************************************** +*/ +//void DebugStart (void) { +//} + +/********************************************************************* +* +* TargetConnect +* +* Function description +* Replaces the default target IF connection routine. Optional. +* +********************************************************************** +*/ +//void TargetConnect (void) { +//} + +/********************************************************************* +* +* BeforeTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +void BeforeTargetConnect (void) { + Project.SetJLinkScript("./MMDScript.JLinkScript"); +} + +/********************************************************************* +* +* AfterTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetConnect (void) { +//} + +/********************************************************************* +* +* TargetDownload +* +* Function description +* Replaces the default program download routine. Optional. +* +********************************************************************** +*/ +//void TargetDownload (void) { +//} + +/********************************************************************* +* +* BeforeTargetDownload +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDownload (void) { +//} + +/********************************************************************* +* +* AfterTargetDownload +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +* +********************************************************************** +*/ +void AfterTargetDownload (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* BeforeTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetHalt +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetHalt (void) { +//} + +/********************************************************************* +* +* BeforeTargetResume +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetResume (void) { +//} + +/********************************************************************* +* +* OnSnapshotLoad +* +* Function description +* Called upon loading a snapshot. Optional. +* +* Additional information +* This function is used to restore the target state in cases +* where values cannot simply be written to the target. +* Typical use: GPIO clock needs to be enabled, before +* GPIO is configured. +* +********************************************************************** +*/ +//void OnSnapshotLoad (void) { +//} + +/********************************************************************* +* +* OnSnapshotSave +* +* Function description +* Called upon saving a snapshot. Optional. +* +* Additional information +* This function is usually used to save values of the target +* state which can either not be trivially read, +* or need to be restored in a specific way or order. +* Typically use: Memory Mapped Registers, +* such as PLL and GPIO configuration. +* +********************************************************************** +*/ +//void OnSnapshotSave (void) { +//} + +/********************************************************************* +* +* OnError +* +* Function description +* Called when an error ocurred. Optional. +* +********************************************************************** +*/ +//void OnError (void) { +//} + +/********************************************************************* +* +* AfterProjectLoad +* +* Function description +* After Project load routine. Optional. +* +********************************************************************** +*/ +//void AfterProjectLoad (void) { +//} + +/********************************************************************* +* +* _SetupTarget +* +* Function description +* Setup the target. +* Called by AfterTargetReset() and AfterTargetDownload(). +* +* Auto-generated function. May be overridden by Ozone. +* +********************************************************************** +*/ +void _SetupTarget(void) { + // + // this function is intentionally empty because both inital PC and + // initial SP were chosen not to be set + // +} diff --git a/core/embed/ble_bootloader/main.c b/core/embed/ble_bootloader/main.c new file mode 100644 index 000000000..4a0112376 --- /dev/null +++ b/core/embed/ble_bootloader/main.c @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be + * reverse engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup bootloader_secure_ble main.c + * @{ + * @ingroup dfu_bootloader_api + * @brief Bootloader project main file for secure DFU. + * + */ + +#include +#include "app_error.h" +#include "app_error_weak.h" +#include "nrf_bootloader.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_dfu_timers.h" +#include "nrf_bootloader_info.h" +#include "nrf_delay.h" +#include "nrf_dfu.h" +#include "nrf_gpio.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" +#include "nrf_mbr.h" +#include "trezor_t3w1_d1_NRF.h" + +static void on_error(void) { + NRF_LOG_FINAL_FLUSH(); + +#if NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT) + // To allow the buffer to be flushed by the host. + nrf_delay_ms(100); +#endif +#ifdef NRF_DFU_DEBUG_VERSION + NRF_BREAKPOINT_COND; +#endif + NVIC_SystemReset(); +} + +void app_error_handler(uint32_t error_code, uint32_t line_num, + const uint8_t* p_file_name) { + NRF_LOG_ERROR("%s:%d, %d", p_file_name, line_num, error_code); + on_error(); +} + +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { + NRF_LOG_ERROR("Received a fault! id: 0x%08x, pc: 0x%08x, info: 0x%08x", id, + pc, info); + on_error(); +} + +void app_error_handler_bare(uint32_t error_code) { + NRF_LOG_ERROR("Received an error: 0x%08x!", error_code); + on_error(); +} + +/** + * @brief Function notifies certain events in DFU process. + */ +static void dfu_observer(nrf_dfu_evt_type_t evt_type) { + switch (evt_type) { + case NRF_DFU_EVT_DFU_FAILED: + case NRF_DFU_EVT_DFU_ABORTED: + case NRF_DFU_EVT_DFU_INITIALIZED: + // bsp_board_init(BSP_INIT_LEDS); + // bsp_board_led_on(BSP_BOARD_LED_0); + // bsp_board_led_on(BSP_BOARD_LED_1); + // bsp_board_led_off(BSP_BOARD_LED_2); + break; + case NRF_DFU_EVT_TRANSPORT_ACTIVATED: + // bsp_board_led_off(BSP_BOARD_LED_1); + // bsp_board_led_on(BSP_BOARD_LED_2); + break; + case NRF_DFU_EVT_DFU_STARTED: + break; + default: + break; + } +} + +uint32_t nrf_dfu_init_user(void) { + // signalize DFU mode + nrf_gpio_pin_set(GPIO_1_PIN); + + return NRF_SUCCESS; +} + +/**@brief Function for application main entry. */ +int main(void) { + NRF_APPROTECT->DISABLE = APPROTECT_DISABLE_DISABLE_SwDisable; + + uint32_t ret_val; + // Apply priority for monitor mode interrupt + NVIC_SetPriority(DebugMonitor_IRQn, _PRIO_SD_LOW); + + // Must happen before flash protection is applied, since it edits a protected + // page. + nrf_bootloader_mbr_addrs_populate(); + + // Protect MBR and bootloader code from being overwritten. + ret_val = nrf_bootloader_flash_protect(0, MBR_SIZE); + APP_ERROR_CHECK(ret_val); + ret_val = + nrf_bootloader_flash_protect(BOOTLOADER_START_ADDR, BOOTLOADER_SIZE); + APP_ERROR_CHECK(ret_val); + + nrf_gpio_cfg_output(GPIO_1_PIN); + nrf_gpio_cfg_output(GPIO_2_PIN); + nrf_gpio_pin_clear(GPIO_1_PIN); + nrf_gpio_pin_clear(GPIO_2_PIN); + + (void)NRF_LOG_INIT(nrf_bootloader_dfu_timer_counter_get); + NRF_LOG_DEFAULT_BACKENDS_INIT(); + + NRF_LOG_INFO("Inside main"); + + ret_val = nrf_bootloader_init(dfu_observer); + APP_ERROR_CHECK(ret_val); + + NRF_LOG_FLUSH(); + + NRF_LOG_ERROR("After main, should never be reached."); + NRF_LOG_FLUSH(); + + APP_ERROR_CHECK_BOOL(false); +} + +/** + * @} + */ diff --git a/core/embed/ble_bootloader/memory.ld b/core/embed/ble_bootloader/memory.ld new file mode 100644 index 000000000..cba932d57 --- /dev/null +++ b/core/embed/ble_bootloader/memory.ld @@ -0,0 +1,156 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x70000, LENGTH = 0xe000 + RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518 + uicr_bootloader_start_address (r) : ORIGIN = 0x10001014, LENGTH = 0x4 + bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 + uicr_mbr_params_page (r) : ORIGIN = 0x10001018, LENGTH = 0x4 + mbr_params_page (r) : ORIGIN = 0x0007E000, LENGTH = 0x1000 +} + +SECTIONS +{ + . = ALIGN(4); + .uicr_bootloader_start_address : + { + PROVIDE(__start_uicr_bootloader_start_address = .); + KEEP(*(SORT(.uicr_bootloader_start_address*))) + PROVIDE(__stop_uicr_bootloader_start_address = .); + } > uicr_bootloader_start_address + . = ALIGN(4); + .bootloader_settings_page(NOLOAD) : + { + PROVIDE(__start_bootloader_settings_page = .); + KEEP(*(SORT(.bootloader_settings_page*))) + PROVIDE(__stop_bootloader_settings_page = .); + } > bootloader_settings_page + . = ALIGN(4); + .uicr_mbr_params_page : + { + PROVIDE(__start_uicr_mbr_params_page = .); + KEEP(*(SORT(.uicr_mbr_params_page*))) + PROVIDE(__stop_uicr_mbr_params_page = .); + } > uicr_mbr_params_page + . = ALIGN(4); + .mbr_params_page(NOLOAD) : + { + PROVIDE(__start_mbr_params_page = .); + KEEP(*(SORT(.mbr_params_page*))) + PROVIDE(__stop_mbr_params_page = .); + } > mbr_params_page +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .dfu_trans : + { + PROVIDE(__start_dfu_trans = .); + KEEP(*(SORT(.dfu_trans*))) + PROVIDE(__stop_dfu_trans = .); + } > FLASH + .svc_data : + { + PROVIDE(__start_svc_data = .); + KEEP(*(.svc_data)) + PROVIDE(__stop_svc_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld" diff --git a/core/embed/ble_bootloader/nrf_bootloader.c b/core/embed/ble_bootloader/nrf_bootloader.c new file mode 100644 index 000000000..f8b3684dd --- /dev/null +++ b/core/embed/ble_bootloader/nrf_bootloader.c @@ -0,0 +1,465 @@ +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be + * reverse engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "nrf_bootloader.h" + +#include "app_scheduler.h" +#include "compiler_abstraction.h" +#include "nordic_common.h" +#include "nrf.h" +#include "nrf_bootloader_app_start.h" +#include "nrf_bootloader_dfu_timers.h" +#include "nrf_bootloader_fw_activation.h" +#include "nrf_bootloader_info.h" +#include "nrf_bootloader_wdt.h" +#include "nrf_delay.h" +#include "nrf_dfu.h" +#include "nrf_dfu_settings.h" +#include "nrf_dfu_utils.h" +#include "nrf_dfu_validation.h" +#include "nrf_error.h" +#include "nrf_gpio.h" +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_power.h" +#include "sdk_config.h" + +static nrf_dfu_observer_t + m_user_observer; //= 100) || + (NRF_BL_DFU_INACTIVITY_TIMEOUT_MS == 0), + "NRF_BL_DFU_INACTIVITY_TIMEOUT_MS must be 100 ms or more, or 0 " + "to indicate that it is disabled."); + +#if defined(NRF_LOG_BACKEND_FLASH_START_PAGE) +STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_START_PAGE != 0, + "If nrf_log flash backend is used it cannot use space after code " + "because it would collide with settings page."); +#endif + +/**@brief Weak implemenation of nrf_dfu_init + * + * @note This function will be overridden if nrf_dfu.c is + * compiled and linked with the project + */ +#if (__LINT__ != 1) +__WEAK uint32_t nrf_dfu_init(nrf_dfu_observer_t observer) { + NRF_LOG_DEBUG("in weak nrf_dfu_init"); + return NRF_SUCCESS; +} +#endif + +/**@brief Weak implementation of nrf_dfu_init + * + * @note This function must be overridden in application if + * user-specific initialization is needed. + */ +__WEAK uint32_t nrf_dfu_init_user(void) { + NRF_LOG_DEBUG("in weak nrf_dfu_init_user"); + return NRF_SUCCESS; +} + +static void flash_write_callback(void* p_context) { + UNUSED_PARAMETER(p_context); + m_flash_write_done = true; +} + +static void do_reset(void* p_context) { + UNUSED_PARAMETER(p_context); + + NRF_LOG_FINAL_FLUSH(); + + nrf_delay_ms(NRF_BL_RESET_DELAY_MS); + + NVIC_SystemReset(); +} + +static void bootloader_reset(bool do_backup) { + NRF_LOG_DEBUG("Resetting bootloader."); + + if (do_backup) { + m_flash_write_done = false; + nrf_dfu_settings_backup(do_reset); + } else { + do_reset(NULL); + } +} + +static void inactivity_timeout(void) { + NRF_LOG_INFO("Inactivity timeout."); + bootloader_reset(true); +} + +/**@brief Function for handling DFU events. + */ +static void dfu_observer(nrf_dfu_evt_type_t evt_type) { + switch (evt_type) { + case NRF_DFU_EVT_DFU_STARTED: + case NRF_DFU_EVT_OBJECT_RECEIVED: + nrf_bootloader_dfu_inactivity_timer_restart( + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS), + inactivity_timeout); + break; + case NRF_DFU_EVT_DFU_COMPLETED: + case NRF_DFU_EVT_DFU_ABORTED: + bootloader_reset(true); + break; + case NRF_DFU_EVT_TRANSPORT_DEACTIVATED: + // Reset the internal state of the DFU settings to the last stored state. + nrf_dfu_settings_reinit(); + break; + default: + break; + } + + if (m_user_observer) { + m_user_observer(evt_type); + } +} + +/**@brief Function for initializing the event scheduler. + */ +static void scheduler_init(void) { + APP_SCHED_INIT(SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); +} + +/**@brief Suspend the CPU until an interrupt occurs. + */ +static void wait_for_event(void) { +#if defined(BLE_STACK_SUPPORT_REQD) || defined(ANT_STACK_SUPPORT_REQD) + (void)sd_app_evt_wait(); +#else + // Wait for an event. + __WFE(); + // Clear the internal event register. + __SEV(); + __WFE(); +#endif +} + +/**@brief Continually sleep and process tasks whenever woken. + */ +static void loop_forever(void) { + while (true) { + // feed the watchdog if enabled. + nrf_bootloader_wdt_feed(); + + app_sched_execute(); + + if (!NRF_LOG_PROCESS()) { + wait_for_event(); + } + } +} + +#if NRF_BL_DFU_ENTER_METHOD_BUTTON +//#ifndef BUTTON_PULL +// #error NRF_BL_DFU_ENTER_METHOD_BUTTON is enabled but not buttons seem to +// be available on the board. +//#endif +/**@brief Function for initializing button used to enter DFU mode. + */ +static void dfu_enter_button_init(void) { + nrf_gpio_cfg_sense_input(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN, + NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW); +} +#endif + +static bool crc_on_valid_app_required(void) { + bool ret = true; + if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET && + (nrf_power_resetreas_get() & NRF_POWER_RESETREAS_OFF_MASK)) { + nrf_power_resetreas_clear(NRF_POWER_RESETREAS_OFF_MASK); + ret = false; + } else if (NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 && + ((nrf_power_gpregret2_get() & BOOTLOADER_DFU_SKIP_CRC_MASK) == + BOOTLOADER_DFU_SKIP_CRC)) { + nrf_power_gpregret2_set(nrf_power_gpregret2_get() & + ~BOOTLOADER_DFU_SKIP_CRC); + ret = false; + } else { + } + + return ret; +} + +static bool boot_validate(boot_validation_t const* p_validation, + uint32_t data_addr, uint32_t data_len) { + return nrf_dfu_validation_boot_validate(p_validation, data_addr, data_len); +} + +/** @brief Function for checking if the main application is valid. + * + * @details This function checks if there is a valid application + * located at Bank 0. + * + * @param[in] do_crc Perform CRC check on application. Only CRC checks + can be skipped. For other boot validation types, + this parameter is ignored. + * + * @retval true If a valid application has been detected. + * @retval false If there is no valid application. + */ +static bool app_is_valid(bool do_crc) { + if (s_dfu_settings.bank_0.bank_code != NRF_DFU_BANK_VALID_APP) { + NRF_LOG_INFO("Boot validation failed. No valid app to boot."); + return false; + } else if (SD_PRESENT && + !boot_validate(&s_dfu_settings.boot_validation_softdevice, + MBR_SIZE, s_dfu_settings.sd_size)) { + NRF_LOG_WARNING( + "Boot validation failed. SoftDevice is present but invalid."); + return false; + } else if (!boot_validate(&s_dfu_settings.boot_validation_app, + nrf_dfu_bank0_start_addr(), + s_dfu_settings.bank_0.image_size)) { + NRF_LOG_WARNING("Boot validation failed. App is invalid."); + return false; + } + // The bootloader itself is not checked, since a self-check of this kind gives + // little to no benefit compared to the cost incurred on each bootup. + + NRF_LOG_DEBUG("App is valid"); + return true; +} + +/**@brief Function for clearing all DFU enter flags that + * preserve state during reset. + * + * @details This is used to make sure that each of these flags + * is checked only once after reset. + */ +static void dfu_enter_flags_clear(void) { + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) { + // Clear RESETPIN flag. + NRF_POWER->RESETREAS |= POWER_RESETREAS_RESETPIN_Msk; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) == + BOOTLOADER_DFU_START)) { + // Clear DFU mark in GPREGRET register. + nrf_power_gpregret_set(nrf_power_gpregret_get() & ~BOOTLOADER_DFU_START); + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) { + // Clear DFU flag in flash settings. + s_dfu_settings.enter_buttonless_dfu = 0; + APP_ERROR_CHECK(nrf_dfu_settings_write(NULL)); + } +} + +/**@brief Function for checking whether to enter DFU mode or not. + */ +static bool dfu_enter_check(void) { + if (!app_is_valid(crc_on_valid_app_required())) { + NRF_LOG_DEBUG("DFU mode because app is not valid."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTON && + (nrf_gpio_pin_read(NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN) == 1)) { + NRF_LOG_DEBUG("DFU mode requested via button."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_PINRESET && + (NRF_POWER->RESETREAS & POWER_RESETREAS_RESETPIN_Msk)) { + NRF_LOG_DEBUG("DFU mode requested via pin-reset."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_GPREGRET && + ((nrf_power_gpregret_get() & BOOTLOADER_DFU_START_MASK) == + BOOTLOADER_DFU_START)) { + NRF_LOG_DEBUG("DFU mode requested via GPREGRET."); + return true; + } + + if (NRF_BL_DFU_ENTER_METHOD_BUTTONLESS && + (s_dfu_settings.enter_buttonless_dfu == 1)) { + NRF_LOG_DEBUG("DFU mode requested via bootloader settings."); + return true; + } + + return false; +} + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +static void postvalidate(void) { + NRF_LOG_INFO("Postvalidating update after reset."); + nrf_dfu_validation_init(); + + if (nrf_dfu_validation_init_cmd_present()) { + uint32_t firmware_start_addr; + uint32_t firmware_size; + + // Execute a previously received init packed. Subsequent executes will have + // no effect. + if (nrf_dfu_validation_init_cmd_execute( + &firmware_start_addr, &firmware_size) == NRF_DFU_RES_CODE_SUCCESS) { + if (nrf_dfu_validation_prevalidate() == NRF_DFU_RES_CODE_SUCCESS) { + if (nrf_dfu_validation_activation_prepare(firmware_start_addr, + firmware_size) == + NRF_DFU_RES_CODE_SUCCESS) { + NRF_LOG_INFO("Postvalidation successful."); + } + } + } + } + + s_dfu_settings.bank_current = NRF_DFU_CURRENT_BANK_0; + UNUSED_RETURN_VALUE(nrf_dfu_settings_write_and_backup(flash_write_callback)); +} +#endif + +ret_code_t nrf_bootloader_init(nrf_dfu_observer_t observer) { + NRF_LOG_DEBUG("In nrf_bootloader_init"); + + ret_code_t ret_val; + nrf_bootloader_fw_activation_result_t activation_result; + uint32_t initial_timeout; + bool dfu_enter = false; + + m_user_observer = observer; + + if (NRF_BL_DEBUG_PORT_DISABLE) { + nrf_bootloader_debug_port_disable(); + } + +#if NRF_BL_DFU_ENTER_METHOD_BUTTON + dfu_enter_button_init(); +#endif + + ret_val = nrf_dfu_settings_init(false); + if (ret_val != NRF_SUCCESS) { + return NRF_ERROR_INTERNAL; + } + +#if NRF_BL_DFU_ALLOW_UPDATE_FROM_APP + // Postvalidate if DFU has signaled that update is ready. + if (s_dfu_settings.bank_current == NRF_DFU_CURRENT_BANK_1) { + postvalidate(); + } +#endif + + // Check if an update needs to be activated and activate it. + activation_result = nrf_bootloader_fw_activate(); + + switch (activation_result) { + case ACTIVATION_NONE: + initial_timeout = + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_INACTIVITY_TIMEOUT_MS); + dfu_enter = dfu_enter_check(); + break; + + case ACTIVATION_SUCCESS_EXPECT_ADDITIONAL_UPDATE: + initial_timeout = + NRF_BOOTLOADER_MS_TO_TICKS(NRF_BL_DFU_CONTINUATION_TIMEOUT_MS); + dfu_enter = true; + break; + + case ACTIVATION_SUCCESS: + bootloader_reset(true); + NRF_LOG_ERROR("Unreachable"); + return NRF_ERROR_INTERNAL; // Should not reach this. + + case ACTIVATION_ERROR: + default: + return NRF_ERROR_INTERNAL; + } + + if (dfu_enter) { + nrf_bootloader_wdt_init(); + scheduler_init(); + dfu_enter_flags_clear(); + + // Call user-defined init function if implemented + ret_val = nrf_dfu_init_user(); + if (ret_val != NRF_SUCCESS) { + return NRF_ERROR_INTERNAL; + } + + nrf_bootloader_dfu_inactivity_timer_restart(initial_timeout, + inactivity_timeout); + + ret_val = nrf_dfu_init(dfu_observer); + if (ret_val != NRF_SUCCESS) { + return NRF_ERROR_INTERNAL; + } + + NRF_LOG_DEBUG("Enter main loop"); + loop_forever(); // This function will never return. + NRF_LOG_ERROR("Unreachable"); + } else { + // Erase additional data like peer data or advertisement name + ret_val = nrf_dfu_settings_additional_erase(); + if (ret_val != NRF_SUCCESS) { + return NRF_ERROR_INTERNAL; + } + + m_flash_write_done = false; + nrf_dfu_settings_backup(flash_write_callback); + ASSERT(m_flash_write_done); + + nrf_bootloader_app_start(); + NRF_LOG_ERROR("Unreachable"); + } + + // Should not be reached. + return NRF_ERROR_INTERNAL; +} diff --git a/core/embed/ble_bootloader/nrf_crypto_allocator.h b/core/embed/ble_bootloader/nrf_crypto_allocator.h new file mode 100644 index 000000000..e4c59bc55 --- /dev/null +++ b/core/embed/ble_bootloader/nrf_crypto_allocator.h @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2019 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be + * reverse engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef NRF_CRYPTO_ALLOCATOR_H__ +#define NRF_CRYPTO_ALLOCATOR_H__ + +#include "nrf_assert.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Crypto library in bootloader case does not use dynamic allocation */ +#define NRF_CRYPTO_ALLOC(size) \ + NULL; \ + ASSERT(0) +#define NRF_CRYPTO_ALLOC_ON_STACK(size) \ + NULL; \ + ASSERT(0) +#define NRF_CRYPTO_FREE(ptr) (void)ptr; + +#ifdef __cplusplus +} +#endif + +#endif /* NRF_CRYPTO_ALLOCATOR_H__ */ diff --git a/core/embed/ble_bootloader/nrf_dfu_serial_uart.c b/core/embed/ble_bootloader/nrf_dfu_serial_uart.c new file mode 100644 index 000000000..579064bbd --- /dev/null +++ b/core/embed/ble_bootloader/nrf_dfu_serial_uart.c @@ -0,0 +1,276 @@ +// clang-format off + +/** + * Copyright (c) 2016 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_dfu_serial.h" + +#include +#include "trezor_t3w1_d1_NRF.h" + +#include "nrf_gpio.h" +#include "nordic_common.h" +#include "app_util_platform.h" +#include "nrf_dfu_transport.h" +#include "nrf_dfu_req_handler.h" +#include "slip.h" +#include "nrf_balloc.h" +#include "nrf_drv_uart.h" + +#define NRF_LOG_MODULE_NAME nrf_dfu_serial_uart +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/**@file + * + * @defgroup nrf_dfu_serial_uart DFU Serial UART transport + * @ingroup nrf_dfu + * @brief Device Firmware Update (DFU) transport layer using UART. + */ + +#define NRF_SERIAL_OPCODE_SIZE (sizeof(uint8_t)) +#define NRF_UART_MAX_RESPONSE_SIZE_SLIP (2 * NRF_SERIAL_MAX_RESPONSE_SIZE + 1) +#define RX_BUF_SIZE (64) //to get 64bytes payload +#define OPCODE_OFFSET (sizeof(uint32_t) - NRF_SERIAL_OPCODE_SIZE) +#define DATA_OFFSET (OPCODE_OFFSET + NRF_SERIAL_OPCODE_SIZE) +#define UART_SLIP_MTU (2 * (RX_BUF_SIZE + 1) + 1) +#define BALLOC_BUF_SIZE ((CEIL_DIV((RX_BUF_SIZE+OPCODE_SIZE),sizeof(uint32_t))*sizeof(uint32_t))) + +NRF_BALLOC_DEF(m_payload_pool, (UART_SLIP_MTU + 1), NRF_DFU_SERIAL_UART_RX_BUFFERS); + +static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0); +static uint8_t m_rx_byte; + +static nrf_dfu_serial_t m_serial; +static slip_t m_slip; +static uint8_t m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP]; +static bool m_active; +static bool m_waiting_for_buffers = false; + +static nrf_dfu_observer_t m_observer; + +static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer); +static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception); + +DFU_TRANSPORT_REGISTER(nrf_dfu_transport_t const uart_dfu_transport) = +{ + .init_func = uart_dfu_transport_init, + .close_func = uart_dfu_transport_close, +}; + +static void payload_free(void * p_buf) +{ + uint8_t * p_buf_root = (uint8_t *)p_buf - DATA_OFFSET; //pointer is shifted to point to data + nrf_balloc_free(&m_payload_pool, p_buf_root); + uint8_t utilization = m_payload_pool.p_stack_limit - m_payload_pool.p_cb->p_stack_pointer; + + if (m_waiting_for_buffers && utilization < NRF_DFU_SERIAL_UART_RX_BUFFERS - 2) { + NRF_LOG_INFO("Buffer utilization: %d, resuming.", utilization); + + nrf_gpio_pin_set(RTS_PIN_NUMBER); + nrf_gpio_cfg_output(RTS_PIN_NUMBER); + m_uart.uarte.p_reg->PSEL.RTS = RTS_PIN_NUMBER; + m_waiting_for_buffers = false; + } + +} + +static ret_code_t rsp_send(uint8_t const * p_data, uint32_t length) +{ + uint32_t slip_len; + (void) slip_encode(m_rsp_buf, (uint8_t *)p_data, length, &slip_len); + + return nrf_drv_uart_tx(&m_uart, m_rsp_buf, slip_len); +} + +static __INLINE void on_rx_complete(nrf_dfu_serial_t * p_transport, uint8_t * p_data, uint8_t len) +{ + ret_code_t ret_code = NRF_ERROR_TIMEOUT; + + // Check if there is byte to process. Zero length transfer means that RXTO occured. + if (len) + { + ret_code = slip_decode_add_byte(&m_slip, p_data[0]); + } + + (void) nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1); + + if (ret_code == NRF_SUCCESS) + { + nrf_dfu_serial_on_packet_received(p_transport, + (uint8_t const *)m_slip.p_buffer, + m_slip.current_index); + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + + uint8_t utilization = m_payload_pool.p_stack_limit - m_payload_pool.p_cb->p_stack_pointer; + + if (!m_waiting_for_buffers && utilization >= NRF_DFU_SERIAL_UART_RX_BUFFERS - 2) { + NRF_LOG_INFO("Buffer utilization: %d, waiting.", utilization); + m_uart.uarte.p_reg->PSEL.RTS = NRF_UART_PSEL_DISCONNECTED; + nrf_gpio_cfg_output(RTS_PIN_NUMBER); + nrf_gpio_pin_set(RTS_PIN_NUMBER); + m_waiting_for_buffers = true; + } + + if (p_rx_buf == NULL) + { + NRF_LOG_ERROR("Failed to allocate buffer"); + return; + } + NRF_LOG_INFO("Allocated buffer %x", p_rx_buf); + // reset the slip decoding + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.state = SLIP_STATE_DECODING; + } + +} + +static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + switch (p_event->type) + { + case NRF_DRV_UART_EVT_RX_DONE: + on_rx_complete((nrf_dfu_serial_t*)p_context, + p_event->data.rxtx.p_data, + p_event->data.rxtx.bytes); + break; + + case NRF_DRV_UART_EVT_ERROR: + APP_ERROR_HANDLER(p_event->data.error.error_mask); + break; + + default: + // No action. + break; + } +} + +static uint32_t uart_dfu_transport_init(nrf_dfu_observer_t observer) +{ + uint32_t err_code = NRF_SUCCESS; + + if (m_active) + { + return err_code; + } + + NRF_LOG_DEBUG("serial_dfu_transport_init()"); + + m_observer = observer; + + err_code = nrf_balloc_init(&m_payload_pool); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + uint8_t * p_rx_buf = nrf_balloc_alloc(&m_payload_pool); + + m_slip.p_buffer = &p_rx_buf[OPCODE_OFFSET]; + m_slip.current_index = 0; + m_slip.buffer_len = UART_SLIP_MTU; + m_slip.state = SLIP_STATE_DECODING; + + m_serial.rsp_func = rsp_send; + m_serial.payload_free_func = payload_free; + m_serial.mtu = UART_SLIP_MTU; + m_serial.p_rsp_buf = &m_rsp_buf[NRF_UART_MAX_RESPONSE_SIZE_SLIP - + NRF_SERIAL_MAX_RESPONSE_SIZE]; + m_serial.p_low_level_transport = &uart_dfu_transport; + + nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG; + + uart_config.pseltxd = TX_PIN_NUMBER; + uart_config.pselrxd = RX_PIN_NUMBER; + uart_config.pselcts = CTS_PIN_NUMBER; + uart_config.pselrts = RTS_PIN_NUMBER; + uart_config.hwfc = NRF_UART_HWFC_ENABLED; + uart_config.p_context = &m_serial; + + nrf_gpio_cfg( + RTS_PIN_NUMBER, + NRF_GPIO_PIN_DIR_OUTPUT, + NRF_GPIO_PIN_INPUT_DISCONNECT, + NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_S0S1, + NRF_GPIO_PIN_NOSENSE); + + + nrf_gpio_pin_write(RTS_PIN_NUMBER, 0); + + err_code = nrf_drv_uart_init(&m_uart, &uart_config, uart_event_handler); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed initializing uart"); + return err_code; + } + + err_code = nrf_drv_uart_rx(&m_uart, &m_rx_byte, 1); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Failed initializing rx"); + } + + NRF_LOG_DEBUG("serial_dfu_transport_init() completed"); + + m_active = true; + + if (m_observer) + { + m_observer(NRF_DFU_EVT_TRANSPORT_ACTIVATED); + } + + return err_code; +} + + +static uint32_t uart_dfu_transport_close(nrf_dfu_transport_t const * p_exception) +{ + if ((m_active == true) && (p_exception != &uart_dfu_transport)) + { + nrf_drv_uart_uninit(&m_uart); + m_active = false; + } + + return NRF_SUCCESS; +} + diff --git a/core/embed/ble_bootloader/priv.pem b/core/embed/ble_bootloader/priv.pem new file mode 100644 index 000000000..a0bab98eb --- /dev/null +++ b/core/embed/ble_bootloader/priv.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIOSMfopjR9WnpAjLnog4xJG5XRVi5MfXk7bGGuxLanCAoAoGCCqGSM49 +AwEHoUQDQgAE9KQi8GEjC+sEphRRaW/GfnCfPJEaKY+oyAw/t0FUL37WzYQEfAos +6HnwYBqys9MYxWRJc0woWfaQGi5I+ptzrQ== +-----END EC PRIVATE KEY----- diff --git a/core/embed/ble_bootloader/sdk_config.h b/core/embed/ble_bootloader/sdk_config.h new file mode 100644 index 000000000..2de38736e --- /dev/null +++ b/core/embed/ble_bootloader/sdk_config.h @@ -0,0 +1,5307 @@ +// clang-format off + +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// nRF_Bootloader + +//========================================================== +// nrf_bootloader - Bootloader settings + +//========================================================== +// Application integrity checks + +//========================================================== +// NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 - Skip CRC integrity check of the application when bit 1 (0-indexed) is set in the GPREGRET2 register. + + +// Only CRC checks can be skipped. For other boot validation types, the GPREGRET2 register is ignored. + +#ifndef NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 +#define NRF_BL_APP_CRC_CHECK_SKIPPED_ON_GPREGRET2 1 +#endif + +// NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET - Skip integrity check of the application when waking up from the System Off state. + + +// Only CRC checks can be skipped. For other boot validation types, the reset state is ignored. + +#ifndef NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET +#define NRF_BL_APP_CRC_CHECK_SKIPPED_ON_SYSTEMOFF_RESET 1 +#endif + +// NRF_BL_APP_SIGNATURE_CHECK_REQUIRED - Perform signature check on the app. Requires the signature to be sent in the init packet. + + +#ifndef NRF_BL_APP_SIGNATURE_CHECK_REQUIRED +#define NRF_BL_APP_SIGNATURE_CHECK_REQUIRED 1 +#endif + +// NRF_BL_DFU_ALLOW_UPDATE_FROM_APP - Whether to allow the app to receive firmware updates for the bootloader to activate. + + +// Enable this to allow the app to instruct the bootloader to activate firmware. +// The bootloader will do its own postvalidation. + +#ifndef NRF_BL_DFU_ALLOW_UPDATE_FROM_APP +#define NRF_BL_DFU_ALLOW_UPDATE_FROM_APP 0 +#endif + +// +//========================================================== + +// DFU mode enter method + +//========================================================== +// NRF_BL_DFU_ENTER_METHOD_BUTTON - Enter DFU mode on button press. +//========================================================== +#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON +#define NRF_BL_DFU_ENTER_METHOD_BUTTON 1 +#endif +// NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN - Button for entering DFU mode. + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) + +#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN +#define NRF_BL_DFU_ENTER_METHOD_BUTTON_PIN 40 +#endif + +// + +// NRF_BL_DFU_ENTER_METHOD_PINRESET - Enter DFU mode on pin reset. + + +#ifndef NRF_BL_DFU_ENTER_METHOD_PINRESET +#define NRF_BL_DFU_ENTER_METHOD_PINRESET 0 +#endif + +// NRF_BL_DFU_ENTER_METHOD_GPREGRET - Enter DFU mode when bit 0 is set in the NRF_POWER_GPREGRET register. + + +#ifndef NRF_BL_DFU_ENTER_METHOD_GPREGRET +#define NRF_BL_DFU_ENTER_METHOD_GPREGRET 1 +#endif + +// NRF_BL_DFU_ENTER_METHOD_BUTTONLESS - Enter DFU mode when the Boolean enter_buttonless_dfu in DFU settings is true. + + +#ifndef NRF_BL_DFU_ENTER_METHOD_BUTTONLESS +#define NRF_BL_DFU_ENTER_METHOD_BUTTONLESS 0 +#endif + +// +//========================================================== + +// DFU timers + +//========================================================== +// NRF_BL_DFU_CONTINUATION_TIMEOUT_MS - Timeout in ms when expecting an update immediately. <100-60000000> + + +// This timeout is used after updating the SoftDevice, when there is +// already a valid application present. The bootloader will enter DFU mode +// for a short time instead of booting the old application to allow the host +// to immediately transfer a new application if it wishes. + +#ifndef NRF_BL_DFU_CONTINUATION_TIMEOUT_MS +#define NRF_BL_DFU_CONTINUATION_TIMEOUT_MS 10000 +#endif + +// NRF_BL_DFU_INACTIVITY_TIMEOUT_MS - Timeout in ms before automatically starting a valid application due to inactivity. <0-60000000> + + +// If 0, no inactivity timer will be used. Values 1-99 are invalid. + +#ifndef NRF_BL_DFU_INACTIVITY_TIMEOUT_MS +#define NRF_BL_DFU_INACTIVITY_TIMEOUT_MS 120000 +#endif + +// +//========================================================== + +// Watchdog timer + +//========================================================== +// NRF_BL_WDT_MAX_SCHEDULER_LATENCY_MS - Maximum latency of the scheduler in miliseconds +// Maximum latency of the scheduler is compared with +// watchdog counter reload value (CRV). If latency is big +// enough, the watchdog will be fed from internal timer +// handler along with feed from user function. If latency +// is smaller than CRV, the watchdog will not be internally fed once +// it will be externally fed. Maximum latency is mainly affected +// by flash operations. + +#ifndef NRF_BL_WDT_MAX_SCHEDULER_LATENCY_MS +#define NRF_BL_WDT_MAX_SCHEDULER_LATENCY_MS 10000 +#endif + +// +//========================================================== + +// Misc Bootloader settings + +//========================================================== +// NRF_BL_DEBUG_PORT_DISABLE - Disable access to the chip via the debug port. + + +// Disable access to the chip via the debug port. +// This modifies the APPROTECT and DEBUGCTRL registers. +// Enable this option in production code if such +// access should be prohibited. Read about the registers +// for more details. + +#ifndef NRF_BL_DEBUG_PORT_DISABLE +#define NRF_BL_DEBUG_PORT_DISABLE 0 +#endif + +// NRF_BL_FW_COPY_PROGRESS_STORE_STEP - Number of pages copied after which progress in the settings page is updated. +// Progress stored in the settings page allows the bootloader to resume +// copying the new firmware in case of interruption (reset). +// If the value is small, then the resume point is more accurate. However, +// it also impacts negatively on flash wear. + +#ifndef NRF_BL_FW_COPY_PROGRESS_STORE_STEP +#define NRF_BL_FW_COPY_PROGRESS_STORE_STEP 8 +#endif + +// NRF_BL_RESET_DELAY_MS - Time to wait before resetting the bootloader. +// Time (in ms) to wait before resetting the bootloader after DFU has been completed or aborted. This allows more time for e.g. disconnecting the BLE link or writing logs. + +#ifndef NRF_BL_RESET_DELAY_MS +#define NRF_BL_RESET_DELAY_MS 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// +//========================================================== + +// nRF_Crypto + +//========================================================== +// NRF_CRYPTO_ENABLED - nrf_crypto - Cryptography library. +//========================================================== +#ifndef NRF_CRYPTO_ENABLED +#define NRF_CRYPTO_ENABLED 1 +#endif + +#ifndef NRF_CRYPTO_HASH_ENABLED +#define NRF_CRYPTO_HASH_ENABLED 1 +#endif + +// NRF_CRYPTO_ALLOCATOR - Memory allocator + + +// Choose memory allocator used by nrf_crypto. Default is alloca if possible or nrf_malloc otherwise. If 'User macros' are selected, the user has to create 'nrf_crypto_allocator.h' file that contains NRF_CRYPTO_ALLOC, NRF_CRYPTO_FREE, and NRF_CRYPTO_ALLOC_ON_STACK. +// <0=> Default +// <1=> User macros +// <2=> On stack (alloca) +// <3=> C dynamic memory (malloc) +// <4=> SDK Memory Manager (nrf_malloc) + +#ifndef NRF_CRYPTO_ALLOCATOR +#define NRF_CRYPTO_ALLOCATOR 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_ENABLED - Enable the ARM Cryptocell CC310 reduced backend. + +// The CC310 hardware-accelerated cryptography backend with reduced functionality and footprint (only available on nRF52840). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED - Enable the secp224r1 elliptic curve support using CC310_BL. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED - Enable the secp256r1 elliptic curve support using CC310_BL. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED - CC310_BL SHA-256 hash functionality. + + +// CC310_BL backend implementation for hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED - nrf_cc310_bl buffers to RAM before running hash operation + + +// Enabling this makes hashing of addresses in FLASH range possible. Size of buffer allocated for hashing is set by NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE - nrf_cc310_bl hash outputs digests in little endian +// Makes the nrf_cc310_bl hash functions output digests in little endian format. Only for use in nRF SDK DFU! + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE 4096 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED - Enable Interrupts while support using CC310 bl. + + +// Select a library version compatible with the configuration. When interrupts are disable, a version named _noint must be used + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_CC310_ENABLED - Enable the ARM Cryptocell CC310 backend. + +// The CC310 hardware-accelerated cryptography backend (only available on nRF52840). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CC310_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED - Enable the AES CBC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED - Enable the AES CTR mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED - Enable the AES ECB mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED - Enable the AES CBC_MAC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED - Enable the AES CMAC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED - Enable the AES CCM mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED - Enable the AES CCM* mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED - Enable the CHACHA-POLY mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED - Enable the secp160r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED - Enable the secp160r2 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED - Enable the secp192r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED - Enable the secp224r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED - Enable the secp256r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED - Enable the secp384r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED - Enable the secp521r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED - Enable the secp160k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED - Enable the secp192k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED - Enable the secp224k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED - Enable the secp256k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED - Enable the Curve25519 curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED - Enable the Ed25519 curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED - CC310 SHA-256 hash functionality. + + +// CC310 backend implementation for hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED - CC310 SHA-512 hash functionality + + +// CC310 backend implementation for SHA-512 (in software). + +#ifndef NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED - CC310 HMAC using SHA-256 + + +// CC310 backend implementation for HMAC using hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED - CC310 HMAC using SHA-512 + + +// CC310 backend implementation for HMAC using SHA-512 (in software). + +#ifndef NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED - Enable RNG support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED - Enable Interrupts while support using CC310. + + +// Select a library version compatible with the configuration. When interrupts are disable, a version named _noint must be used + +#ifndef NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_CIFRA_ENABLED - Enable the Cifra backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CIFRA_ENABLED +#define NRF_CRYPTO_BACKEND_CIFRA_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED - Enable the AES EAX mode using Cifra. + + +#ifndef NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED +#define NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED - Enable the mbed TLS backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED - Enable the AES CBC mode mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED - Enable the AES CTR mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED - Enable the AES CFB mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED - Enable the AES ECB mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED - Enable the AES CBC MAC mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED - Enable the AES CMAC mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED - Enable the AES CCM mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED - Enable the AES GCM mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve + + +// Enable this setting if you need secp192r1 (NIST 192-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED - Enable secp224r1 (NIST 224-bit) curve + + +// Enable this setting if you need secp224r1 (NIST 224-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED - Enable secp256r1 (NIST 256-bit) curve + + +// Enable this setting if you need secp256r1 (NIST 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED - Enable secp384r1 (NIST 384-bit) curve + + +// Enable this setting if you need secp384r1 (NIST 384-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED - Enable secp521r1 (NIST 521-bit) curve + + +// Enable this setting if you need secp521r1 (NIST 521-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED - Enable secp192k1 (Koblitz 192-bit) curve + + +// Enable this setting if you need secp192k1 (Koblitz 192-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED - Enable secp224k1 (Koblitz 224-bit) curve + + +// Enable this setting if you need secp224k1 (Koblitz 224-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED - Enable secp256k1 (Koblitz 256-bit) curve + + +// Enable this setting if you need secp256k1 (Koblitz 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED - Enable bp256r1 (Brainpool 256-bit) curve + + +// Enable this setting if you need bp256r1 (Brainpool 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED - Enable bp384r1 (Brainpool 384-bit) curve + + +// Enable this setting if you need bp384r1 (Brainpool 384-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED - Enable bp512r1 (Brainpool 512-bit) curve + + +// Enable this setting if you need bp512r1 (Brainpool 512-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED - Enable Curve25519 curve + + +// Enable this setting if you need Curve25519 support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED - Enable mbed TLS SHA-256 hash functionality. + + +// mbed TLS backend implementation for SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED - Enable mbed TLS SHA-512 hash functionality. + + +// mbed TLS backend implementation for SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED - Enable mbed TLS HMAC using SHA-256. + + +// mbed TLS backend implementation for HMAC using SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED - Enable mbed TLS HMAC using SHA-512. + + +// mbed TLS backend implementation for HMAC using SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED - Enable the micro-ecc backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve + + +// Enable this setting if you need secp192r1 (NIST 192-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED - Enable secp224r1 (NIST 224-bit) curve + + +// Enable this setting if you need secp224r1 (NIST 224-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED - Enable secp256r1 (NIST 256-bit) curve + + +// Enable this setting if you need secp256r1 (NIST 256-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED - Enable secp256k1 (Koblitz 256-bit) curve + + +// Enable this setting if you need secp256k1 (Koblitz 256-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED - Enable the nRF HW RNG backend. + +// The nRF HW backend provide access to RNG peripheral in nRF5x devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED - Enable mbed TLS CTR-DRBG algorithm. + + +// Enable mbed TLS CTR-DRBG standardized by NIST (NIST SP 800-90A Rev. 1). The nRF HW RNG is used as an entropy source for seeding. + +#ifndef NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_NRF_SW_ENABLED - Enable the legacy nRFx sw for crypto. + +// The nRF SW cryptography backend (only used in bootloader context). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_NRF_SW_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_SW_ENABLED 1 +#endif +// NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED - nRF SW hash backend support for SHA-256 + + +// The nRF SW backend provide access to nRF SDK legacy hash implementation of SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_OBERON_ENABLED - Enable the Oberon backend + +// The Oberon backend +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_OBERON_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED - Enable the CHACHA-POLY mode using Oberon. + + +#ifndef NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED - Enable secp256r1 curve + + +// Enable this setting if you need secp256r1 curve support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED - Enable Curve25519 ECDH + + +// Enable this setting if you need Curve25519 ECDH support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED - Enable Ed25519 signature scheme + + +// Enable this setting if you need Ed25519 support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED - Oberon SHA-256 hash functionality + + +// Oberon backend implementation for SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED - Oberon SHA-512 hash functionality + + +// Oberon backend implementation for SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED - Oberon HMAC using SHA-256 + + +// Oberon backend implementation for HMAC using SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED - Oberon HMAC using SHA-512 + + +// Oberon backend implementation for HMAC using SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED 0 +#endif + +// + +// NRF_CRYPTO_BACKEND_OPTIGA_ENABLED - Enable the nrf_crypto Optiga Trust X backend. + +// Enables the nrf_crypto backend for Optiga Trust X devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED - Optiga backend support for RNG + + +// The Optiga backend provide external chip RNG. + +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED - Optiga backend support for ECC secp256r1 + + +// The Optiga backend provide external chip ECC using secp256r1. + +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED - Big-endian byte order in raw Curve25519 data + + +// Enable big-endian byte order in Curve25519 API, if set to 1. Use little-endian, if set to 0. + +#ifndef NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED +#define NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED 0 +#endif + +// + +// nrf_crypto_rng - RNG Configuration + +//========================================================== +// NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED - Use static memory buffers for context and temporary init buffer. + + +// Always recommended when using the nRF HW RNG as the context and temporary buffers are small. Consider disabling if using the CC310 RNG in a RAM constrained application. In this case, memory must be provided to nrf_crypto_rng_init, or it can be allocated internally provided that NRF_CRYPTO_ALLOCATOR does not allocate memory on the stack. + +#ifndef NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED +#define NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED 1 +#endif + +// NRF_CRYPTO_RNG_AUTO_INIT_ENABLED - Initialize the RNG module automatically when nrf_crypto is initialized. + + +// Automatic initialization is only supported with static or internally allocated context and temporary memory. + +#ifndef NRF_CRYPTO_RNG_AUTO_INIT_ENABLED +#define NRF_CRYPTO_RNG_AUTO_INIT_ENABLED 1 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_DFU + +//========================================================== +// DFU security - nrf_dfu_validation - DFU validation + +//========================================================== +// NRF_DFU_APP_ACCEPT_SAME_VERSION - Whether to accept application upgrades with the same version as the current application. + + +// This applies to application updates, and possibly to SoftDevice updates. +// Bootloader upgrades always require higher versions. SoftDevice upgrades +// look at the sd_req field independently of this config. +// Disabling this protects against replay attacks wearing out the flash of the device. +// This config only has an effect when NRF_DFU_APP_DOWNGRADE_PREVENTION is enabled. + +#ifndef NRF_DFU_APP_ACCEPT_SAME_VERSION +#define NRF_DFU_APP_ACCEPT_SAME_VERSION 1 +#endif + +// NRF_DFU_APP_DOWNGRADE_PREVENTION - Check the firmware version and SoftDevice requirements of application (and SoftDevice) updates. + + +// Whether to check the incoming version against the version of the existing app and/or +// the incoming SoftDevice requirements against the existing SoftDevice. +// This applies to application updates, and possibly to SoftDevice updates. +// Disabling this causes the checks to always ignore the incoming firmware version and +// to ignore the SoftDevice requirements if the first requirement is 0. +// This does not apply the bootloader updates. If the bootloader depends on the SoftDevice +// e.g. for BLE transport, this does not apply to SoftDevice updates. +// See @ref lib_bootloader_dfu_validation for more information. +// When signed updates are required, version checking should always be enabled. + +#ifndef NRF_DFU_APP_DOWNGRADE_PREVENTION +#define NRF_DFU_APP_DOWNGRADE_PREVENTION 1 +#endif + +// NRF_DFU_EXTERNAL_APP_VERSIONING - Require versioning for external applications. + + +// This configuration is only used if NRF_DFU_SUPPORTS_EXTERNAL_APP is set to 1. +// Setting this will require that any FW images using the FW upgrade type +// DFU_FW_TYPE_EXTERNAL_APPLICATION must follow a monotonic versioning scheme +// where the FW version of an upgrade must always be larger than the previously stored +// FW version. + +#ifndef NRF_DFU_EXTERNAL_APP_VERSIONING +#define NRF_DFU_EXTERNAL_APP_VERSIONING 1 +#endif + +// NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES - Accept only dual-bank application updates. + + +// If not enabled then if there is not enough space to perform dual-bank update +// application is deleted and single-bank update is performed. In case it is considered +// security concern user can prefer to discard update request rather than overwrite +// current application. + +#ifndef NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES +#define NRF_DFU_FORCE_DUAL_BANK_APP_UPDATES 0 +#endif + +// NRF_DFU_HW_VERSION - Device hardware version. +// This is used to determine if given update is targeting the device. +// It is checked against the hw_version value in the init packet + +#ifndef NRF_DFU_HW_VERSION +#define NRF_DFU_HW_VERSION 52 +#endif + +// NRF_DFU_REQUIRE_SIGNED_APP_UPDATE - Require a valid signature to update the application or SoftDevice. + + +#ifndef NRF_DFU_REQUIRE_SIGNED_APP_UPDATE +#define NRF_DFU_REQUIRE_SIGNED_APP_UPDATE 1 +#endif + +// NRF_DFU_SINGLE_BANK_APP_UPDATES - Place the application and the SoftDevice directly where they are supposed to be. + + +// Note that this creates security concerns when signing and version checks +// are enabled. An attacker will be able to delete (but not replace) +// the current app or SoftDevice without knowing the signature key. + +#ifndef NRF_DFU_SINGLE_BANK_APP_UPDATES +#define NRF_DFU_SINGLE_BANK_APP_UPDATES 0 +#endif + +// +//========================================================== + +// NRF_DFU_SETTINGS_COMPATIBILITY_MODE - nrf_dfu_settings - DFU Settings + + +#ifndef NRF_DFU_SETTINGS_COMPATIBILITY_MODE +#define NRF_DFU_SETTINGS_COMPATIBILITY_MODE 0 +#endif + +// nrf_dfu - Device Firmware Upgrade + +//========================================================== +// DFU transport + +//========================================================== +// NRF_DFU_TRANSPORT_ANT - ANT transport settings +//========================================================== +#ifndef NRF_DFU_TRANSPORT_ANT +#define NRF_DFU_TRANSPORT_ANT 0 +#endif +// NRF_DFU_ANT_MTU - MTU size used for firmware bursts. +// Sets the maximum burst size used for DFU write commands. + +#ifndef NRF_DFU_ANT_MTU +#define NRF_DFU_ANT_MTU 1024 +#endif + +// ANT DFU buffers + +//========================================================== +// NRF_DFU_ANT_BUFFERS_OVERRIDE + +// Check this option to override the default number of buffers. +//========================================================== +#ifndef NRF_DFU_ANT_BUFFERS_OVERRIDE +#define NRF_DFU_ANT_BUFFERS_OVERRIDE 0 +#endif +// NRF_DFU_ANT_BUFFERS - Number of buffers in the ANT transport. +// Number of buffers to store incoming data while it is being written to flash. +// Reduce this value to save RAM. If this value is too low, the DFU process will fail. + +#ifndef NRF_DFU_ANT_BUFFERS +#define NRF_DFU_ANT_BUFFERS 8 +#endif + +// + +// +//========================================================== + +// ANT DFU Channel Configuration + +//========================================================== +// NRF_DFU_ANT_RF_FREQ - DFU RF channel. +#ifndef NRF_DFU_ANT_RF_FREQ +#define NRF_DFU_ANT_RF_FREQ 66 +#endif + +// NRF_DFU_ANT_DEV_TYPE - Device type field to use for DFU channel id. +#ifndef NRF_DFU_ANT_DEV_TYPE +#define NRF_DFU_ANT_DEV_TYPE 10 +#endif + +// NRF_DFU_ANT_CHANNEL_PERIOD - Channel period of DFU ANT channel. +#ifndef NRF_DFU_ANT_CHANNEL_PERIOD +#define NRF_DFU_ANT_CHANNEL_PERIOD 2048 +#endif + +// +//========================================================== + +// + +// NRF_DFU_TRANSPORT_BLE - BLE transport settings +//========================================================== +#ifndef NRF_DFU_TRANSPORT_BLE +#define NRF_DFU_TRANSPORT_BLE 0 +#endif +// NRF_DFU_BLE_SKIP_SD_INIT - Skip the SoftDevice and interrupt vector table initialization. + + +#ifndef NRF_DFU_BLE_SKIP_SD_INIT +#define NRF_DFU_BLE_SKIP_SD_INIT 0 +#endif + +// NRF_DFU_BLE_ADV_NAME - Default advertising name. +#ifndef NRF_DFU_BLE_ADV_NAME +#define NRF_DFU_BLE_ADV_NAME "DfuTarg" +#endif + +// NRF_DFU_BLE_ADV_INTERVAL - Advertising interval (in units of 0.625 ms) +#ifndef NRF_DFU_BLE_ADV_INTERVAL +#define NRF_DFU_BLE_ADV_INTERVAL 40 +#endif + +// BLE DFU security + +//========================================================== +// NRF_DFU_BLE_REQUIRES_BONDS - Require bond with peer. + + +#ifndef NRF_DFU_BLE_REQUIRES_BONDS +#define NRF_DFU_BLE_REQUIRES_BONDS 0 +#endif + +// +//========================================================== + +// BLE DFU connection + +//========================================================== +// NRF_DFU_BLE_MIN_CONN_INTERVAL - Minimum connection interval (units). +// Minimum GAP connection interval, in 1.25 ms units. + +#ifndef NRF_DFU_BLE_MIN_CONN_INTERVAL +#define NRF_DFU_BLE_MIN_CONN_INTERVAL 12 +#endif + +// NRF_DFU_BLE_MAX_CONN_INTERVAL - Maximum connection interval (units). +// Maximum GAP connection interval, in 1.25 ms units. + +#ifndef NRF_DFU_BLE_MAX_CONN_INTERVAL +#define NRF_DFU_BLE_MAX_CONN_INTERVAL 12 +#endif + +// NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS - Supervision timeout (ms). +// GAP connection supervision timeout, in milliseconds. + +#ifndef NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS +#define NRF_DFU_BLE_CONN_SUP_TIMEOUT_MS 6000 +#endif + +// +//========================================================== + +// BLE DFU buffers + +//========================================================== +// NRF_DFU_BLE_BUFFERS_OVERRIDE + +// Check this option to override the default number of buffers. +//========================================================== +#ifndef NRF_DFU_BLE_BUFFERS_OVERRIDE +#define NRF_DFU_BLE_BUFFERS_OVERRIDE 0 +#endif +// NRF_DFU_BLE_BUFFERS - Number of buffers in the BLE transport. +// Number of buffers to store incoming data while it is being written to flash. +// Reduce this value to save RAM. If this value is too low, the DFU process will fail. + +#ifndef NRF_DFU_BLE_BUFFERS +#define NRF_DFU_BLE_BUFFERS 8 +#endif + +// + +// +//========================================================== + +// + +// +//========================================================== + +// DFU protocol + +//========================================================== +// NRF_DFU_PROTOCOL_FW_VERSION_MSG - Firmware version message support. + + +// Firmware version message support. +// If disabled, firmware version requests will return NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED. + +#ifndef NRF_DFU_PROTOCOL_FW_VERSION_MSG +#define NRF_DFU_PROTOCOL_FW_VERSION_MSG 1 +#endif + +// NRF_DFU_PROTOCOL_REDUCED - Reduced protocol opcode selection. + + +// Only support a minimal set of opcodes; return NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED +// for unsupported opcodes. The supported opcodes are:NRF_DFU_OP_OBJECT_CREATE, +// NRF_DFU_OP_OBJECT_EXECUTE, NRF_DFU_OP_OBJECT_SELECT, NRF_DFU_OP_OBJECT_WRITE, +// NRF_DFU_OP_CRC_GET, NRF_DFU_OP_RECEIPT_NOTIF_SET, and NRF_DFU_OP_ABORT. +// This reduced feature set is used by the BLE transport to reduce flash usage. + +#ifndef NRF_DFU_PROTOCOL_REDUCED +#define NRF_DFU_PROTOCOL_REDUCED 0 +#endif + +// NRF_DFU_PROTOCOL_VERSION_MSG - Protocol version message support. + + +// Protocol version message support. +// If disabled, protocol version requests will return NRF_DFU_RES_CODE_OP_CODE_NOT_SUPPORTED. + +#ifndef NRF_DFU_PROTOCOL_VERSION_MSG +#define NRF_DFU_PROTOCOL_VERSION_MSG 1 +#endif + +// +//========================================================== + +// Misc DFU settings + +//========================================================== +// NRF_DFU_APP_DATA_AREA_SIZE - The size (in bytes) of the flash area reserved for application data. +// This area is found at the end of the application area, next to the start of +// the bootloader. This area will not be erased by the bootloader during a +// firmware upgrade. The size must be a multiple of the flash page size. + +#ifndef NRF_DFU_APP_DATA_AREA_SIZE +#define NRF_DFU_APP_DATA_AREA_SIZE 12288 +#endif + +// NRF_DFU_IN_APP - Specifies that this code is in the app, not the bootloader, so some settings are off-limits. + + +// Enable this to disable writing to areas of the settings that are protected +// by the bootlader. If this is not enabled in the app, certain settings write +// operations will cause HardFaults or will be ignored. Enabling this option +// also causes postvalidation to be disabled since this is meant to be done +// in the bootloader. NRF_BL_DFU_ALLOW_UPDATE_FROM_APP must be enabled in the bootloader. + +#ifndef NRF_DFU_IN_APP +#define NRF_DFU_IN_APP 0 +#endif + +// NRF_DFU_SAVE_PROGRESS_IN_FLASH - Save DFU progress in flash. + + +// Save DFU progress to flash so that it can be resumed if interrupted, instead of being restarted. +// Keep this setting disabled to maximize transfer speed and minimize flash wear. +// The init packet is always saved in flash, regardless of this setting. + +#ifndef NRF_DFU_SAVE_PROGRESS_IN_FLASH +#define NRF_DFU_SAVE_PROGRESS_IN_FLASH 0 +#endif + +// NRF_DFU_SUPPORTS_EXTERNAL_APP - [Experimental] Support for external app. + + +// External apps are apps that will not be activated. They can +// e.g. be apps to be sent to a third party. External app updates +// are verified upon reception, but will remain in bank 1, and +// will never be booted. An external app will be overwritten if +// a new DFU procedure is performed. Note: This functionality is +// experimental and not yet used in any examples. + +#ifndef NRF_DFU_SUPPORTS_EXTERNAL_APP +#define NRF_DFU_SUPPORTS_EXTERNAL_APP 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nrf_dfu_serial_uart - UART DFU transport + +//========================================================== +// NRF_DFU_SERIAL_UART_USES_HWFC - HWFC configuration + + +#ifndef NRF_DFU_SERIAL_UART_USES_HWFC +#define NRF_DFU_SERIAL_UART_USES_HWFC 1 +#endif + +// NRF_DFU_SERIAL_UART_RX_BUFFERS - Number of RX buffers. +// Number of buffers depends on flash access vs. +// transport throughtput. If value is too low it may lead +// to received packets being dropped. + +#ifndef NRF_DFU_SERIAL_UART_RX_BUFFERS +#define NRF_DFU_SERIAL_UART_RX_BUFFERS 10 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Drivers + +//========================================================== +// NRFX_PRS_ENABLED - nrfx_prs - Peripheral Resource Sharing module +//========================================================== +#ifndef NRFX_PRS_ENABLED +#define NRFX_PRS_ENABLED 1 +#endif +// NRFX_PRS_BOX_0_ENABLED - Enables box 0 in the module. + + +#ifndef NRFX_PRS_BOX_0_ENABLED +#define NRFX_PRS_BOX_0_ENABLED 0 +#endif + +// NRFX_PRS_BOX_1_ENABLED - Enables box 1 in the module. + + +#ifndef NRFX_PRS_BOX_1_ENABLED +#define NRFX_PRS_BOX_1_ENABLED 0 +#endif + +// NRFX_PRS_BOX_2_ENABLED - Enables box 2 in the module. + + +#ifndef NRFX_PRS_BOX_2_ENABLED +#define NRFX_PRS_BOX_2_ENABLED 0 +#endif + +// NRFX_PRS_BOX_3_ENABLED - Enables box 3 in the module. + + +#ifndef NRFX_PRS_BOX_3_ENABLED +#define NRFX_PRS_BOX_3_ENABLED 0 +#endif + +// NRFX_PRS_BOX_4_ENABLED - Enables box 4 in the module. + + +#ifndef NRFX_PRS_BOX_4_ENABLED +#define NRFX_PRS_BOX_4_ENABLED 1 +#endif + +// NRFX_PRS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PRS_CONFIG_LOG_ENABLED +#define NRFX_PRS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PRS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PRS_CONFIG_LOG_LEVEL +#define NRFX_PRS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PRS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_INFO_COLOR +#define NRFX_PRS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PRS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_DEBUG_COLOR +#define NRFX_PRS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UARTE_ENABLED - nrfx_uarte - UARTE peripheral driver +//========================================================== +#ifndef NRFX_UARTE_ENABLED +#define NRFX_UARTE_ENABLED 1 +#endif +// NRFX_UARTE0_ENABLED - Enable UARTE0 instance +#ifndef NRFX_UARTE0_ENABLED +#define NRFX_UARTE0_ENABLED 0 +#endif + +// NRFX_UARTE1_ENABLED - Enable UARTE1 instance +#ifndef NRFX_UARTE1_ENABLED +#define NRFX_UARTE1_ENABLED 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_HWFC +#define NRFX_UARTE_DEFAULT_CONFIG_HWFC 1 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_PARITY +#define NRFX_UARTE_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <8388608=> 31250 baud +// <10289152=> 38400 baud +// <15007744=> 56000 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UARTE_CONFIG_LOG_ENABLED +#define NRFX_UARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UARTE_CONFIG_LOG_LEVEL +#define NRFX_UARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_INFO_COLOR +#define NRFX_UARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_DEBUG_COLOR +#define NRFX_UARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UART_ENABLED - nrfx_uart - UART peripheral driver +//========================================================== +#ifndef NRFX_UART_ENABLED +#define NRFX_UART_ENABLED 1 +#endif +// NRFX_UART0_ENABLED - Enable UART0 instance +#ifndef NRFX_UART0_ENABLED +#define NRFX_UART0_ENABLED 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UART_DEFAULT_CONFIG_HWFC +#define NRFX_UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UART_DEFAULT_CONFIG_PARITY +#define NRFX_UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3866624=> 14400 baud +// <5152768=> 19200 baud +// <7729152=> 28800 baud +// <8388608=> 31250 baud +// <10309632=> 38400 baud +// <15007744=> 56000 baud +// <15462400=> 57600 baud +// <20615168=> 76800 baud +// <30924800=> 115200 baud +// <61845504=> 230400 baud +// <67108864=> 250000 baud +// <123695104=> 460800 baud +// <247386112=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UART_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE 268435456 +#endif + +// NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UART_CONFIG_LOG_ENABLED +#define NRFX_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UART_CONFIG_LOG_LEVEL +#define NRFX_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_INFO_COLOR +#define NRFX_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_DEBUG_COLOR +#define NRFX_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 1 +#endif +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 1 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 268435456 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 0 +#endif + +// UART0_ENABLED - Enable UART0 instance +//========================================================== +#ifndef UART0_ENABLED +#define UART0_ENABLED 1 +#endif +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// UART1_ENABLED - Enable UART1 instance +//========================================================== +#ifndef UART1_ENABLED +#define UART1_ENABLED 0 +#endif +// + +// + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_SCHEDULER_ENABLED - app_scheduler - Events scheduler +//========================================================== +#ifndef APP_SCHEDULER_ENABLED +#define APP_SCHEDULER_ENABLED 1 +#endif +// APP_SCHEDULER_WITH_PAUSE - Enabling pause feature + + +#ifndef APP_SCHEDULER_WITH_PAUSE +#define APP_SCHEDULER_WITH_PAUSE 0 +#endif + +// APP_SCHEDULER_WITH_PROFILER - Enabling scheduler profiling + + +#ifndef APP_SCHEDULER_WITH_PROFILER +#define APP_SCHEDULER_WITH_PROFILER 0 +#endif + +// + +// CRC32_ENABLED - crc32 - CRC32 calculation routines + + +#ifndef CRC32_ENABLED +#define CRC32_ENABLED 1 +#endif + +// MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator +//========================================================== +#ifndef MEM_MANAGER_ENABLED +#define MEM_MANAGER_ENABLED 1 +#endif +// MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block. <0-255> + + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT 1 +#endif + +// MEMORY_MANAGER_SMALL_BLOCK_SIZE - Size of each memory blocks identified as 'small' block. +// Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE 32 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block. <0-255> + + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_SIZE - Size of each memory blocks identified as 'medium' block. +// Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block. <0-255> + + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_SIZE - Size of each memory blocks identified as 'large' block. +// Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra large' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 1320 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra large' block. +// Size of each memory blocks identified as 'extra extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 3444 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra small' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 64 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra small' block. +// Size of each memory blocks identified as 'extra extra small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 32 +#endif + +// MEM_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef MEM_MANAGER_CONFIG_LOG_ENABLED +#define MEM_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// MEM_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef MEM_MANAGER_CONFIG_LOG_LEVEL +#define MEM_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// MEM_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MEM_MANAGER_CONFIG_INFO_COLOR +#define MEM_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// MEM_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MEM_MANAGER_CONFIG_DEBUG_COLOR +#define MEM_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MEM_MANAGER_DISABLE_API_PARAM_CHECK - Disable API parameter checks in the module. + + +#ifndef MEM_MANAGER_DISABLE_API_PARAM_CHECK +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK 0 +#endif + +// + +// NRF_BALLOC_ENABLED - nrf_balloc - Block allocator module +//========================================================== +#ifndef NRF_BALLOC_ENABLED +#define NRF_BALLOC_ENABLED 1 +#endif +// NRF_BALLOC_CONFIG_DEBUG_ENABLED - Enables debug mode in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_CONFIG_DEBUG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS - Number of words used as head guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS +#define NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS - Number of words used as tail guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS +#define NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED - Enables basic checks in this module. + + +#ifndef NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED +#define NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED - Enables double memory free check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED - Enables free memory corruption check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_BALLOC_CLI_CMDS +#define NRF_BALLOC_CLI_CMDS 0 +#endif + +// + +// + +// NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library +//========================================================== +#ifndef NRF_FSTORAGE_ENABLED +#define NRF_FSTORAGE_ENABLED 1 +#endif +// nrf_fstorage - Common settings + +// Common settings to all fstorage implementations +//========================================================== +// NRF_FSTORAGE_PARAM_CHECK_DISABLED - Disable user input validation + + +// If selected, use ASSERT to validate user input. +// This effectively removes user input validation in production code. +// Recommended setting: OFF, only enable this setting if size is a major concern. + +#ifndef NRF_FSTORAGE_PARAM_CHECK_DISABLED +#define NRF_FSTORAGE_PARAM_CHECK_DISABLED 1 +#endif + +// +//========================================================== + +// nrf_fstorage_sd - Implementation using the SoftDevice + +// Configuration options for the fstorage implementation using the SoftDevice +//========================================================== +// NRF_FSTORAGE_SD_QUEUE_SIZE - Size of the internal queue of operations +// Increase this value if API calls frequently return the error @ref NRF_ERROR_NO_MEM. + +#ifndef NRF_FSTORAGE_SD_QUEUE_SIZE +#define NRF_FSTORAGE_SD_QUEUE_SIZE 16 +#endif + +// NRF_FSTORAGE_SD_MAX_RETRIES - Maximum number of attempts at executing an operation when the SoftDevice is busy +// Increase this value if events frequently return the @ref NRF_ERROR_TIMEOUT error. +// The SoftDevice might fail to schedule flash access due to high BLE activity. + +#ifndef NRF_FSTORAGE_SD_MAX_RETRIES +#define NRF_FSTORAGE_SD_MAX_RETRIES 8 +#endif + +// NRF_FSTORAGE_SD_MAX_WRITE_SIZE - Maximum number of bytes to be written to flash in a single operation +// This value must be a multiple of four. +// Lowering this value can increase the chances of the SoftDevice being able to execute flash operations in between radio activity. +// This value is bound by the maximum number of bytes that can be written to flash in a single call to @ref sd_flash_write. +// That is 1024 bytes for nRF51 ICs and 4096 bytes for nRF52 ICs. + +#ifndef NRF_FSTORAGE_SD_MAX_WRITE_SIZE +#define NRF_FSTORAGE_SD_MAX_WRITE_SIZE 20 +#endif + +// +//========================================================== + +// + +// NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module + + +#ifndef NRF_MEMOBJ_ENABLED +#define NRF_MEMOBJ_ENABLED 1 +#endif + +// NRF_QUEUE_ENABLED - nrf_queue - Queue module +//========================================================== +#ifndef NRF_QUEUE_ENABLED +#define NRF_QUEUE_ENABLED 0 +#endif +// NRF_QUEUE_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_QUEUE_CLI_CMDS +#define NRF_QUEUE_CLI_CMDS 0 +#endif + +// + +// NRF_STRERROR_ENABLED - nrf_strerror - Library for converting error code to string. + + +#ifndef NRF_STRERROR_ENABLED +#define NRF_STRERROR_ENABLED 1 +#endif + +// SLIP_ENABLED - slip - SLIP encoding and decoding + + +#ifndef SLIP_ENABLED +#define SLIP_ENABLED 1 +#endif + +// nrf_fprintf - fprintf function. + +//========================================================== +// NRF_FPRINTF_ENABLED - Enable/disable fprintf module. + + +#ifndef NRF_FPRINTF_ENABLED +#define NRF_FPRINTF_ENABLED 1 +#endif + +// NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED - For each printed LF, function will add CR. + + +#ifndef NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED +#define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 1 +#endif + +// NRF_FPRINTF_DOUBLE_ENABLED - Enable IEEE-754 double precision formatting. + + +#ifndef NRF_FPRINTF_DOUBLE_ENABLED +#define NRF_FPRINTF_DOUBLE_ENABLED 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Log +#ifdef DEBUG_NRF +//========================================================== +// NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend +//========================================================== +#ifndef NRF_LOG_BACKEND_RTT_ENABLED +#define NRF_LOG_BACKEND_RTT_ENABLED 1 +#endif +// NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS - Period before retrying writing to RTT +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS +#define NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS 1 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_CNT - Writing to RTT retries. +// If RTT fails to accept any new data after retries +// module assumes that host is not active and on next +// request it will perform only one write attempt. +// On successful writing, module assumes that host is active +// and scheme with retry is applied again. + +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_CNT +#define NRF_LOG_BACKEND_RTT_TX_RETRY_CNT 3 +#endif + +// + +// NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend +//========================================================== +#ifndef NRF_LOG_BACKEND_UART_ENABLED +#define NRF_LOG_BACKEND_UART_ENABLED 0 +#endif +// NRF_LOG_BACKEND_UART_TX_PIN - UART TX pin +#ifndef NRF_LOG_BACKEND_UART_TX_PIN +#define NRF_LOG_BACKEND_UART_TX_PIN 6 +#endif + +// NRF_LOG_BACKEND_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRF_LOG_BACKEND_UART_BAUDRATE +#define NRF_LOG_BACKEND_UART_BAUDRATE 30801920 +#endif + +// NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE 64 +#endif + +#endif + +// + +// NRF_LOG_ENABLED - nrf_log - Logger +//========================================================== +#ifndef NRF_LOG_ENABLED +#ifdef DEBUG_NRF +#define NRF_LOG_ENABLED 1 +#else +#define NRF_LOG_ENABLED 0 +#endif +#endif +// Log message pool - Configuration of log message pool + +//========================================================== +// NRF_LOG_MSGPOOL_ELEMENT_SIZE - Size of a single element in the pool of memory objects. +// If a small value is set, then performance of logs processing +// is degraded because data is fragmented. Bigger value impacts +// RAM memory utilization. The size is set to fit a message with +// a timestamp and up to 2 arguments in a single memory object. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_SIZE +#define NRF_LOG_MSGPOOL_ELEMENT_SIZE 20 +#endif + +// NRF_LOG_MSGPOOL_ELEMENT_COUNT - Number of elements in the pool of memory objects +// If a small value is set, then it may lead to a deadlock +// in certain cases if backend has high latency and holds +// multiple messages for long time. Bigger value impacts +// RAM memory usage. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_COUNT +#define NRF_LOG_MSGPOOL_ELEMENT_COUNT 8 +#endif + +// +//========================================================== + +// NRF_LOG_ALLOW_OVERFLOW - Configures behavior when circular buffer is full. + + +// If set then oldest logs are overwritten. Otherwise a +// marker is injected informing about overflow. + +#ifndef NRF_LOG_ALLOW_OVERFLOW +#define NRF_LOG_ALLOW_OVERFLOW 1 +#endif + +// NRF_LOG_BUFSIZE - Size of the buffer for storing logs (in bytes). + + +// Must be power of 2 and multiple of 4. +// If NRF_LOG_DEFERRED = 0 then buffer size can be reduced to minimum. +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 +// <2048=> 2048 +// <4096=> 4096 +// <8192=> 8192 +// <16384=> 16384 + +#ifndef NRF_LOG_BUFSIZE +#ifdef DEBUG_NRF +#define NRF_LOG_BUFSIZE 4096 +#else +#define NRF_LOG_BUFSIZE 1024 +#endif +#endif + +// NRF_LOG_CLI_CMDS - Enable CLI commands for the module. + + +#ifndef NRF_LOG_CLI_CMDS +#define NRF_LOG_CLI_CMDS 0 +#endif + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#ifdef DEBUG_NRF +#define NRF_LOG_DEFAULT_LEVEL 4 +#else +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + + +// Log data is buffered and can be processed in idle. + +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 1 +#endif + +// NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. + + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +// NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED - Enable use of critical region for non deffered mode when flushing logs. + + +// When enabled NRF_LOG_FLUSH is called from critical section when non deffered mode is used. +// Log output will never be corrupted as access to the log backend is exclusive +// but system will spend significant amount of time in critical section + +#ifndef NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED +#define NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED 0 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 2 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 4 +#endif + +// + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + +// Function for getting the timestamp is provided by the user +//========================================================== +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif +// NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY - Default frequency of the timestamp (in Hz) or 0 to use app_timer frequency. +#ifndef NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY +#define NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY 0 +#endif + +// + +// nrf_log module configuration + +//========================================================== +// nrf_log in nRF_Core + +//========================================================== +// NRF_MPU_LIB_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MPU_LIB_CONFIG_LOG_ENABLED +#define NRF_MPU_LIB_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MPU_LIB_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MPU_LIB_CONFIG_LOG_LEVEL +#define NRF_MPU_LIB_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MPU_LIB_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_INFO_COLOR +#define NRF_MPU_LIB_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MPU_LIB_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_DEBUG_COLOR +#define NRF_MPU_LIB_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_STACK_GUARD_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_STACK_GUARD_CONFIG_LOG_ENABLED +#define NRF_STACK_GUARD_CONFIG_LOG_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_STACK_GUARD_CONFIG_LOG_LEVEL +#define NRF_STACK_GUARD_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_STACK_GUARD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_INFO_COLOR +#define NRF_STACK_GUARD_CONFIG_INFO_COLOR 0 +#endif + +// NRF_STACK_GUARD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_DEBUG_COLOR +#define NRF_STACK_GUARD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TASK_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TASK_MANAGER_CONFIG_LOG_ENABLED +#define TASK_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// TASK_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TASK_MANAGER_CONFIG_LOG_LEVEL +#define TASK_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// TASK_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_INFO_COLOR +#define TASK_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// TASK_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_DEBUG_COLOR +#define TASK_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Drivers + +//========================================================== +// CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef CLOCK_CONFIG_LOG_ENABLED +#define CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef CLOCK_CONFIG_LOG_LEVEL +#define CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_INFO_COLOR +#define CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_DEBUG_COLOR +#define CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMP_CONFIG_LOG_ENABLED +#define COMP_CONFIG_LOG_ENABLED 0 +#endif +// COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMP_CONFIG_LOG_LEVEL +#define COMP_CONFIG_LOG_LEVEL 3 +#endif + +// COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_INFO_COLOR +#define COMP_CONFIG_INFO_COLOR 0 +#endif + +// COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_DEBUG_COLOR +#define COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef GPIOTE_CONFIG_LOG_ENABLED +#define GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef GPIOTE_CONFIG_LOG_LEVEL +#define GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_INFO_COLOR +#define GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_DEBUG_COLOR +#define GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef LPCOMP_CONFIG_LOG_ENABLED +#define LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef LPCOMP_CONFIG_LOG_LEVEL +#define LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_INFO_COLOR +#define LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_DEBUG_COLOR +#define LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MAX3421E_HOST_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef MAX3421E_HOST_CONFIG_LOG_ENABLED +#define MAX3421E_HOST_CONFIG_LOG_ENABLED 0 +#endif +// MAX3421E_HOST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef MAX3421E_HOST_CONFIG_LOG_LEVEL +#define MAX3421E_HOST_CONFIG_LOG_LEVEL 3 +#endif + +// MAX3421E_HOST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_INFO_COLOR +#define MAX3421E_HOST_CONFIG_INFO_COLOR 0 +#endif + +// MAX3421E_HOST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_DEBUG_COLOR +#define MAX3421E_HOST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRFX_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef NRFX_USBD_CONFIG_LOG_ENABLED +#define NRFX_USBD_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_USBD_CONFIG_LOG_LEVEL +#define NRFX_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_INFO_COLOR +#define NRFX_USBD_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_DEBUG_COLOR +#define NRFX_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PDM_CONFIG_LOG_ENABLED +#define PDM_CONFIG_LOG_ENABLED 0 +#endif +// PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PDM_CONFIG_LOG_LEVEL +#define PDM_CONFIG_LOG_LEVEL 3 +#endif + +// PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_INFO_COLOR +#define PDM_CONFIG_INFO_COLOR 0 +#endif + +// PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_DEBUG_COLOR +#define PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PPI_CONFIG_LOG_ENABLED +#define PPI_CONFIG_LOG_ENABLED 0 +#endif +// PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PPI_CONFIG_LOG_LEVEL +#define PPI_CONFIG_LOG_LEVEL 3 +#endif + +// PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_INFO_COLOR +#define PPI_CONFIG_INFO_COLOR 0 +#endif + +// PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_DEBUG_COLOR +#define PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PWM_CONFIG_LOG_ENABLED +#define PWM_CONFIG_LOG_ENABLED 0 +#endif +// PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PWM_CONFIG_LOG_LEVEL +#define PWM_CONFIG_LOG_LEVEL 3 +#endif + +// PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_INFO_COLOR +#define PWM_CONFIG_INFO_COLOR 0 +#endif + +// PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_DEBUG_COLOR +#define PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef QDEC_CONFIG_LOG_ENABLED +#define QDEC_CONFIG_LOG_ENABLED 0 +#endif +// QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef QDEC_CONFIG_LOG_LEVEL +#define QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_INFO_COLOR +#define QDEC_CONFIG_INFO_COLOR 0 +#endif + +// QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_DEBUG_COLOR +#define QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RNG_CONFIG_LOG_ENABLED +#define RNG_CONFIG_LOG_ENABLED 0 +#endif +// RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RNG_CONFIG_LOG_LEVEL +#define RNG_CONFIG_LOG_LEVEL 3 +#endif + +// RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_INFO_COLOR +#define RNG_CONFIG_INFO_COLOR 0 +#endif + +// RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_DEBUG_COLOR +#define RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED - Enables logging of random numbers. + + +#ifndef RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED +#define RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED 0 +#endif + +// + +// RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RTC_CONFIG_LOG_ENABLED +#define RTC_CONFIG_LOG_ENABLED 0 +#endif +// RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RTC_CONFIG_LOG_LEVEL +#define RTC_CONFIG_LOG_LEVEL 3 +#endif + +// RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_INFO_COLOR +#define RTC_CONFIG_INFO_COLOR 0 +#endif + +// RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_DEBUG_COLOR +#define RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SAADC_CONFIG_LOG_ENABLED +#define SAADC_CONFIG_LOG_ENABLED 0 +#endif +// SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SAADC_CONFIG_LOG_LEVEL +#define SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_INFO_COLOR +#define SAADC_CONFIG_INFO_COLOR 0 +#endif + +// SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_DEBUG_COLOR +#define SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPIS_CONFIG_LOG_ENABLED +#define SPIS_CONFIG_LOG_ENABLED 0 +#endif +// SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPIS_CONFIG_LOG_LEVEL +#define SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_INFO_COLOR +#define SPIS_CONFIG_INFO_COLOR 0 +#endif + +// SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_DEBUG_COLOR +#define SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TIMER_CONFIG_LOG_ENABLED +#define TIMER_CONFIG_LOG_ENABLED 0 +#endif +// TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TIMER_CONFIG_LOG_LEVEL +#define TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_INFO_COLOR +#define TIMER_CONFIG_INFO_COLOR 0 +#endif + +// TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_DEBUG_COLOR +#define TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWIS_CONFIG_LOG_ENABLED +#define TWIS_CONFIG_LOG_ENABLED 0 +#endif +// TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWIS_CONFIG_LOG_LEVEL +#define TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_INFO_COLOR +#define TWIS_CONFIG_INFO_COLOR 0 +#endif + +// TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_DEBUG_COLOR +#define TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWI_CONFIG_LOG_ENABLED +#define TWI_CONFIG_LOG_ENABLED 0 +#endif +// TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWI_CONFIG_LOG_LEVEL +#define TWI_CONFIG_LOG_LEVEL 3 +#endif + +// TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_INFO_COLOR +#define TWI_CONFIG_INFO_COLOR 0 +#endif + +// TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_DEBUG_COLOR +#define TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef UART_CONFIG_LOG_ENABLED +#define UART_CONFIG_LOG_ENABLED 0 +#endif +// UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef UART_CONFIG_LOG_LEVEL +#define UART_CONFIG_LOG_LEVEL 3 +#endif + +// UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_INFO_COLOR +#define UART_CONFIG_INFO_COLOR 0 +#endif + +// UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_DEBUG_COLOR +#define UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef USBD_CONFIG_LOG_ENABLED +#define USBD_CONFIG_LOG_ENABLED 0 +#endif +// USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef USBD_CONFIG_LOG_LEVEL +#define USBD_CONFIG_LOG_LEVEL 3 +#endif + +// USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_INFO_COLOR +#define USBD_CONFIG_INFO_COLOR 0 +#endif + +// USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_DEBUG_COLOR +#define USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef WDT_CONFIG_LOG_ENABLED +#define WDT_CONFIG_LOG_ENABLED 0 +#endif +// WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef WDT_CONFIG_LOG_LEVEL +#define WDT_CONFIG_LOG_LEVEL 3 +#endif + +// WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_INFO_COLOR +#define WDT_CONFIG_INFO_COLOR 0 +#endif + +// WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_DEBUG_COLOR +#define WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Libraries + +//========================================================== +// APP_BUTTON_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_BUTTON_CONFIG_LOG_ENABLED +#define APP_BUTTON_CONFIG_LOG_ENABLED 0 +#endif +// APP_BUTTON_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_LOG_LEVEL +#define APP_BUTTON_CONFIG_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL +#define APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_INFO_COLOR +#define APP_BUTTON_CONFIG_INFO_COLOR 0 +#endif + +// APP_BUTTON_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_DEBUG_COLOR +#define APP_BUTTON_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_TIMER_CONFIG_LOG_ENABLED +#define APP_TIMER_CONFIG_LOG_ENABLED 0 +#endif +// APP_TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_LOG_LEVEL +#define APP_TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_INITIAL_LOG_LEVEL +#define APP_TIMER_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_INFO_COLOR +#define APP_TIMER_CONFIG_INFO_COLOR 0 +#endif + +// APP_TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_DEBUG_COLOR +#define APP_TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CDC_ACM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define APP_USBD_CDC_ACM_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#define APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module. +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CONFIG_LOG_LEVEL +#define APP_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_INFO_COLOR +#define APP_USBD_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_DEBUG_COLOR +#define APP_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_DUMMY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_DUMMY_CONFIG_LOG_ENABLED +#define APP_USBD_DUMMY_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_DUMMY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_DUMMY_CONFIG_LOG_LEVEL +#define APP_USBD_DUMMY_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_DUMMY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_INFO_COLOR +#define APP_USBD_DUMMY_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_DUMMY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_DEBUG_COLOR +#define APP_USBD_DUMMY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_MSC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_MSC_CONFIG_LOG_ENABLED +#define APP_USBD_MSC_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_MSC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_MSC_CONFIG_LOG_LEVEL +#define APP_USBD_MSC_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_MSC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_INFO_COLOR +#define APP_USBD_MSC_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_MSC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_DEBUG_COLOR +#define APP_USBD_MSC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_ATFIFO_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_ATFIFO_CONFIG_LOG_ENABLED +#define NRF_ATFIFO_CONFIG_LOG_ENABLED 0 +#endif +// NRF_ATFIFO_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_INFO_COLOR +#define NRF_ATFIFO_CONFIG_INFO_COLOR 0 +#endif + +// NRF_ATFIFO_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_DEBUG_COLOR +#define NRF_ATFIFO_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BALLOC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_LOG_ENABLED +#define NRF_BALLOC_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_LOG_LEVEL +#define NRF_BALLOC_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL +#define NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_INFO_COLOR +#define NRF_BALLOC_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BALLOC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_DEBUG_COLOR +#define NRF_BALLOC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_BLE_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_CLI_BLE_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_CLI_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_MEMOBJ_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MEMOBJ_CONFIG_LOG_ENABLED +#define NRF_MEMOBJ_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MEMOBJ_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MEMOBJ_CONFIG_LOG_LEVEL +#define NRF_MEMOBJ_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MEMOBJ_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_INFO_COLOR +#define NRF_MEMOBJ_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MEMOBJ_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_DEBUG_COLOR +#define NRF_MEMOBJ_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#define NRF_PWR_MGMT_CONFIG_LOG_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_PWR_MGMT_CONFIG_LOG_LEVEL +#define NRF_PWR_MGMT_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_PWR_MGMT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_INFO_COLOR +#define NRF_PWR_MGMT_CONFIG_INFO_COLOR 0 +#endif + +// NRF_PWR_MGMT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#define NRF_PWR_MGMT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_QUEUE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_QUEUE_CONFIG_LOG_ENABLED +#define NRF_QUEUE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_QUEUE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_LEVEL +#define NRF_QUEUE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_INFO_COLOR +#define NRF_QUEUE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_QUEUE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_DEBUG_COLOR +#define NRF_QUEUE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_ANT_LOG_ENABLED - Enable logging in SoftDevice handler (ANT) module. +//========================================================== +#ifndef NRF_SDH_ANT_LOG_ENABLED +#define NRF_SDH_ANT_LOG_ENABLED 0 +#endif +// NRF_SDH_ANT_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_ANT_LOG_LEVEL +#define NRF_SDH_ANT_LOG_LEVEL 3 +#endif + +// NRF_SDH_ANT_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_INFO_COLOR +#define NRF_SDH_ANT_INFO_COLOR 0 +#endif + +// NRF_SDH_ANT_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_DEBUG_COLOR +#define NRF_SDH_ANT_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_BLE_LOG_ENABLED - Enable logging in SoftDevice handler (BLE) module. +//========================================================== +#ifndef NRF_SDH_BLE_LOG_ENABLED +#define NRF_SDH_BLE_LOG_ENABLED 0 +#endif +// NRF_SDH_BLE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_BLE_LOG_LEVEL +#define NRF_SDH_BLE_LOG_LEVEL 3 +#endif + +// NRF_SDH_BLE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_INFO_COLOR +#define NRF_SDH_BLE_INFO_COLOR 0 +#endif + +// NRF_SDH_BLE_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_DEBUG_COLOR +#define NRF_SDH_BLE_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_LOG_ENABLED - Enable logging in SoftDevice handler module. +//========================================================== +#ifndef NRF_SDH_LOG_ENABLED +#define NRF_SDH_LOG_ENABLED 0 +#endif +// NRF_SDH_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_LOG_LEVEL +#define NRF_SDH_LOG_LEVEL 3 +#endif + +// NRF_SDH_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_INFO_COLOR +#define NRF_SDH_INFO_COLOR 0 +#endif + +// NRF_SDH_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_DEBUG_COLOR +#define NRF_SDH_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_SOC_LOG_ENABLED - Enable logging in SoftDevice handler (SoC) module. +//========================================================== +#ifndef NRF_SDH_SOC_LOG_ENABLED +#define NRF_SDH_SOC_LOG_ENABLED 0 +#endif +// NRF_SDH_SOC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_SOC_LOG_LEVEL +#define NRF_SDH_SOC_LOG_LEVEL 3 +#endif + +// NRF_SDH_SOC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_INFO_COLOR +#define NRF_SDH_SOC_INFO_COLOR 0 +#endif + +// NRF_SDH_SOC_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_DEBUG_COLOR +#define NRF_SDH_SOC_DEBUG_COLOR 0 +#endif + +// + +// NRF_SORTLIST_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_SORTLIST_CONFIG_LOG_ENABLED +#define NRF_SORTLIST_CONFIG_LOG_ENABLED 0 +#endif +// NRF_SORTLIST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SORTLIST_CONFIG_LOG_LEVEL +#define NRF_SORTLIST_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_SORTLIST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_INFO_COLOR +#define NRF_SORTLIST_CONFIG_INFO_COLOR 0 +#endif + +// NRF_SORTLIST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_DEBUG_COLOR +#define NRF_SORTLIST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_TWI_SENSOR_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_ENABLED +#define NRF_TWI_SENSOR_CONFIG_LOG_ENABLED 0 +#endif +// NRF_TWI_SENSOR_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_LEVEL +#define NRF_TWI_SENSOR_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_TWI_SENSOR_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_INFO_COLOR +#define NRF_TWI_SENSOR_CONFIG_INFO_COLOR 0 +#endif + +// NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR +#define NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PM_LOG_ENABLED - Enable logging in Peer Manager and its submodules. +//========================================================== +#ifndef PM_LOG_ENABLED +#define PM_LOG_ENABLED 1 +#endif +// PM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PM_LOG_LEVEL +#define PM_LOG_LEVEL 3 +#endif + +// PM_LOG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_INFO_COLOR +#define PM_LOG_INFO_COLOR 0 +#endif + +// PM_LOG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_DEBUG_COLOR +#define PM_LOG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Serialization + +//========================================================== +// SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED +#define SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED 0 +#endif +// SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL +#define SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL 3 +#endif + +// SER_HAL_TRANSPORT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_INFO_COLOR +#define SER_HAL_TRANSPORT_CONFIG_INFO_COLOR 0 +#endif + +// SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR +#define SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// +//========================================================== + +// + +// NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED - nrf_log_str_formatter - Log string formatter + + +#ifndef NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED +#define NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED 1 +#endif + +// +//========================================================== + +// nRF_Segger_RTT + +//========================================================== +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 4096 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Maximum number of upstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of downstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Maximum number of downstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/core/embed/ble_bootloader/settings.hex b/core/embed/ble_bootloader/settings.hex new file mode 100644 index 000000000..4406d2ad1 --- /dev/null +++ b/core/embed/ble_bootloader/settings.hex @@ -0,0 +1,104 @@ +:020000040007F3 +:10E000005021D2AF0200000000000000000000001C +:10E01000000000000000000080820100C0F8B7B4DA +:10E0200001000000000000000000000000000000EF +:10E030000000000034560200000000000000000054 +:10E0400000000000000000000000000000000000D0 +:10E0500000000000000000000000000000000000C0 +:10E0600000000000000000000000000000000000B0 +:10E0700000000000000000000000000000000000A0 +:10E080000000000000000000000000000000000090 +:10E090000000000000000000000000000000000080 +:10E0A0000000000000000000000000000000000070 +:10E0B0000000000000000000000000000000000060 +:10E0C0000000000000000000000000000000000050 +:10E0D0000000000000000000000000000000000040 +:10E0E0000000000000000000000000000000000030 +:10E0F0000000000000000000000000000000000020 +:10E10000000000000000000000000000000000000F +:10E1100000000000000000000000000000000000FF +:10E1200000000000000000000000000000000000EF +:10E1300000000000000000000000000000000000DF +:10E1400000000000000000000000000000000000CF +:10E1500000000000000000000000000000000000BF +:10E1600000000000000000000000000000000000AF +:10E17000000000000000000000000000000000009F +:10E18000000000000000000000000000000000008F +:10E19000000000000000000000000000000000007F +:10E1A000000000000000000000000000000000006F +:10E1B000000000000000000000000000000000005F +:10E1C000000000000000000000000000000000004F +:10E1D000000000000000000000000000000000003F +:10E1E000000000000000000000000000000000002F +:10E1F000000000000000000000000000000000001F +:10E20000000000000000000000000000000000000E +:10E2100000000000000000000000000000000000FE +:10E2200000000000000000000000000000000000EE +:10E2300000000000000000000000000000000000DE +:10E2400000000000000000000000000000000000CE +:10E250000000000000000000000000008AEF67D40A +:10E26000039C5C1C98A20BBD8ABFB9C46939106BB2 +:10E27000B47E723565915A51FAC818DE94DD6E8C01 +:10E280002BD8C489343239712A38D616C1A9482C02 +:10E29000CDA78E5E28F37D0E3AF147DF285C80170C +:10E2A00071035B9F4D32703D914A924FB5B9142076 +:10E2B000EE2F84400F8681CD396EC8C55C811676FD +:10E2C000EC52E336EE8EF89DB5B57AAF4C54E69736 +:10E2D000A3E5472CD695C51C2E4EB86E56EE19F503 +:10E2E00051AE00000000000000000000000000002F +:10E2F000000000000000000000000000000000001E +:10E30000000000000000000000000000000000000D +:10E3100000000000000000000000000000000000FD +:04E32000000000FFFA +:10F000005021D2AF0200000000000000000000000C +:10F01000000000000000000080820100C0F8B7B4CA +:10F0200001000000000000000000000000000000DF +:10F030000000000034560200000000000000000044 +:10F0400000000000000000000000000000000000C0 +:10F0500000000000000000000000000000000000B0 +:10F0600000000000000000000000000000000000A0 +:10F070000000000000000000000000000000000090 +:10F080000000000000000000000000000000000080 +:10F090000000000000000000000000000000000070 +:10F0A0000000000000000000000000000000000060 +:10F0B0000000000000000000000000000000000050 +:10F0C0000000000000000000000000000000000040 +:10F0D0000000000000000000000000000000000030 +:10F0E0000000000000000000000000000000000020 +:10F0F0000000000000000000000000000000000010 +:10F1000000000000000000000000000000000000FF +:10F1100000000000000000000000000000000000EF +:10F1200000000000000000000000000000000000DF +:10F1300000000000000000000000000000000000CF +:10F1400000000000000000000000000000000000BF +:10F1500000000000000000000000000000000000AF +:10F16000000000000000000000000000000000009F +:10F17000000000000000000000000000000000008F +:10F18000000000000000000000000000000000007F +:10F19000000000000000000000000000000000006F +:10F1A000000000000000000000000000000000005F +:10F1B000000000000000000000000000000000004F +:10F1C000000000000000000000000000000000003F +:10F1D000000000000000000000000000000000002F +:10F1E000000000000000000000000000000000001F +:10F1F000000000000000000000000000000000000F +:10F2000000000000000000000000000000000000FE +:10F2100000000000000000000000000000000000EE +:10F2200000000000000000000000000000000000DE +:10F2300000000000000000000000000000000000CE +:10F2400000000000000000000000000000000000BE +:10F250000000000000000000000000008AEF67D4FA +:10F26000039C5C1C98A20BBD8ABFB9C46939106BA2 +:10F27000B47E723565915A51FAC818DE94DD6E8CF1 +:10F280002BD8C489343239712A38D616C1A9482CF2 +:10F29000CDA78E5E28F37D0E3AF147DF285C8017FC +:10F2A00071035B9F4D32703D914A924FB5B9142066 +:10F2B000EE2F84400F8681CD396EC8C55C811676ED +:10F2C000EC52E336EE8EF89DB5B57AAF4C54E69726 +:10F2D000A3E5472CD695C51C2E4EB86E56EE19F5F3 +:10F2E00051AE00000000000000000000000000001F +:10F2F000000000000000000000000000000000000E +:10F3000000000000000000000000000000000000FD +:10F3100000000000000000000000000000000000ED +:04F32000000000FFEA +:00000001FF diff --git a/core/embed/ble_bootloader/version.h b/core/embed/ble_bootloader/version.h new file mode 100644 index 000000000..14de53045 --- /dev/null +++ b/core/embed/ble_bootloader/version.h @@ -0,0 +1,4 @@ +#define VERSION_MAJOR 0 +#define VERSION_MINOR 0 +#define VERSION_PATCH 0 +#define VERSION_BUILD 0 diff --git a/core/embed/ble_firmware/advertising.c b/core/embed/ble_firmware/advertising.c new file mode 100644 index 000000000..b7665017b --- /dev/null +++ b/core/embed/ble_firmware/advertising.c @@ -0,0 +1,203 @@ +#include "ble_gap.h" + +#include "advertising.h" +#include "ble_advdata.h" +#include "ble_advertising.h" +#include "ble_nus.h" +#include "connection.h" +#include "defs.h" +#include "int_comm.h" +#include "nrf_log.h" +#include "pm.h" +#include "power.h" + +#define APP_ADV_INTERVAL \ + 64 /**< The advertising interval (in units of 0.625 ms. This value \ + corresponds to 40 ms). */ + +#define APP_ADV_DURATION \ + 18000 /**< The advertising duration (180 seconds) in units of 10 \ + milliseconds. */ + +#define NUS_SERVICE_UUID_TYPE \ + BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service \ + (vendor specific). */ + +static ble_uuid_t m_adv_uuids[] = /**< Universally unique service identifier. */ + {{BLE_UUID_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}}; + +BLE_ADVERTISING_DEF(m_advertising); /**< Advertising module instance. */ + +/**@brief Function for handling advertising events. + * + * @details This function will be called for advertising events which are passed + * to the application. + * + * @param[in] ble_adv_evt Advertising event. + */ +static void on_adv_evt(ble_adv_evt_t ble_adv_evt) { + uint32_t err_code; + + switch (ble_adv_evt) { + case BLE_ADV_EVT_DIRECTED_HIGH_DUTY: + NRF_LOG_INFO("High Duty Directed advertising."); + send_status_event(); + break; + + case BLE_ADV_EVT_DIRECTED: + NRF_LOG_INFO("Directed advertising."); + send_status_event(); + break; + + case BLE_ADV_EVT_FAST: + NRF_LOG_INFO("Fast advertising."); + send_status_event(); + break; + + case BLE_ADV_EVT_SLOW: + NRF_LOG_INFO("Slow advertising."); + send_status_event(); + break; + + case BLE_ADV_EVT_FAST_WHITELIST: + NRF_LOG_INFO("Fast advertising with whitelist."); + send_status_event(); + break; + + case BLE_ADV_EVT_SLOW_WHITELIST: + NRF_LOG_INFO("Slow advertising with whitelist."); + send_status_event(); + break; + + case BLE_ADV_EVT_IDLE: + send_status_event(); + // sleep_mode_enter(); + break; + + case BLE_ADV_EVT_WHITELIST_REQUEST: { + ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t addr_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + uint32_t irk_cnt = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + err_code = pm_whitelist_get(whitelist_addrs, &addr_cnt, whitelist_irks, + &irk_cnt); + if (err_code != NRF_ERROR_NOT_FOUND) { + APP_ERROR_CHECK(err_code); + } else { + break; + } + NRF_LOG_DEBUG( + "pm_whitelist_get returns %d addr in whitelist and %d irk whitelist", + addr_cnt, irk_cnt); + + // Set the correct identities list (no excluding peers with no Central + // Address Resolution). + identities_set(PM_PEER_ID_LIST_SKIP_NO_IRK); + + // Apply the whitelist. + err_code = ble_advertising_whitelist_reply( + &m_advertising, whitelist_addrs, addr_cnt, whitelist_irks, irk_cnt); + APP_ERROR_CHECK(err_code); + } break; // BLE_ADV_EVT_WHITELIST_REQUEST + + case BLE_ADV_EVT_PEER_ADDR_REQUEST: { + pm_peer_data_bonding_t peer_bonding_data; + + // Only Give peer address if we have a handle to the bonded peer. + if (get_peer_id() != PM_PEER_ID_INVALID) { + err_code = pm_peer_data_bonding_load(get_peer_id(), &peer_bonding_data); + if (err_code != NRF_ERROR_NOT_FOUND) { + APP_ERROR_CHECK(err_code); + + // Manipulate identities to exclude peers with no Central Address + // Resolution. + identities_set(PM_PEER_ID_LIST_SKIP_ALL); + + ble_gap_addr_t *p_peer_addr = + &(peer_bonding_data.peer_ble_id.id_addr_info); + err_code = + ble_advertising_peer_addr_reply(&m_advertising, p_peer_addr); + APP_ERROR_CHECK(err_code); + } + } + } break; // BLE_ADV_EVT_PEER_ADDR_REQUEST + + default: + break; + } +} + +void advertising_init(void) { + uint32_t err_code; + uint8_t adv_flags; + ble_advertising_init_t init; + + memset(&init, 0, sizeof(init)); + + adv_flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; + init.advdata.name_type = BLE_ADVDATA_FULL_NAME; + init.advdata.include_appearance = false; + init.advdata.flags = adv_flags; + init.advdata.uuids_complete.uuid_cnt = 0; + init.advdata.uuids_complete.p_uuids = NULL; + + init.config.ble_adv_whitelist_enabled = true; + init.config.ble_adv_directed_high_duty_enabled = true; + init.config.ble_adv_directed_enabled = false; + init.config.ble_adv_directed_interval = 0; + init.config.ble_adv_directed_timeout = 0; + init.config.ble_adv_fast_enabled = true; + init.config.ble_adv_fast_interval = APP_ADV_INTERVAL; + init.config.ble_adv_fast_timeout = APP_ADV_DURATION; + + init.evt_handler = on_adv_evt; + + init.srdata.uuids_more_available.uuid_cnt = + sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]); + init.srdata.uuids_more_available.p_uuids = m_adv_uuids; + + err_code = ble_advertising_init(&m_advertising, &init); + APP_ERROR_CHECK(err_code); + + ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG); +} + +void advertising_start(bool whitelist) { + m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = false; + + if (m_advertising.adv_mode_current != BLE_ADV_MODE_DIRECTED_HIGH_DUTY) { + if (m_advertising.adv_mode_current != BLE_ADV_MODE_FAST && + get_connection_handle() == BLE_CONN_HANDLE_INVALID) { + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + + ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST); + APP_ERROR_CHECK(ret); + } + + if (!whitelist) { + ret_code_t ret = + ble_advertising_restart_without_whitelist(&m_advertising); + APP_ERROR_CHECK(ret); + } + } +} + +void advertising_stop(void) { + m_advertising.adv_modes_config.ble_adv_on_disconnect_disabled = true; + ret_code_t ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_IDLE); + APP_ERROR_CHECK(ret); + // ret =sd_ble_gap_disconnect(get_connection_handle(), + // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(ret); +} + +void advertising_restart_without_whitelist(void) { + ret_code_t ret = ble_advertising_restart_without_whitelist(&m_advertising); + APP_ERROR_CHECK(ret); +} + +bool is_advertising(void) { + return m_advertising.adv_mode_current != BLE_ADV_MODE_IDLE; +} + +bool is_advertising_wl(void) { return m_advertising.whitelist_in_use; } diff --git a/core/embed/ble_firmware/advertising.h b/core/embed/ble_firmware/advertising.h new file mode 100644 index 000000000..02c7af44c --- /dev/null +++ b/core/embed/ble_firmware/advertising.h @@ -0,0 +1,18 @@ +#ifndef __ADVERTISING__ +#define __ADVERTISING__ + +#include + +void advertising_init(void); + +void advertising_start(bool whitelist); + +void advertising_stop(void); + +void advertising_restart_without_whitelist(void); + +bool is_advertising(void); + +bool is_advertising_wl(void); + +#endif diff --git a/core/embed/ble_firmware/ble_nus.c b/core/embed/ble_firmware/ble_nus.c new file mode 100644 index 000000000..d2dad7b09 --- /dev/null +++ b/core/embed/ble_firmware/ble_nus.c @@ -0,0 +1,356 @@ +// clang-format off + +/** + * Copyright (c) 2012 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "sdk_common.h" +#if NRF_MODULE_ENABLED(BLE_NUS) +#include "ble.h" +#include "ble_nus.h" +#include "ble_srv_common.h" + +#define NRF_LOG_MODULE_NAME ble_nus +#if BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL BLE_NUS_CONFIG_LOG_LEVEL +#define NRF_LOG_INFO_COLOR BLE_NUS_CONFIG_INFO_COLOR +#define NRF_LOG_DEBUG_COLOR BLE_NUS_CONFIG_DEBUG_COLOR +#else // BLE_NUS_CONFIG_LOG_ENABLED +#define NRF_LOG_LEVEL 0 +#endif // BLE_NUS_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + + +#define BLE_UUID_NUS_TX_CHARACTERISTIC 0x0003 /**< The UUID of the TX Characteristic. */ +#define BLE_UUID_NUS_RX_CHARACTERISTIC 0x0002 /**< The UUID of the RX Characteristic. */ + +#define BLE_NUS_MAX_RX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the RX Characteristic (in bytes). */ +#define BLE_NUS_MAX_TX_CHAR_LEN BLE_NUS_MAX_DATA_LEN /**< Maximum length of the TX Characteristic (in bytes). */ + +#define NUS_BASE_UUID {{0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x00, 0x00, 0x40, 0x6E}} /**< Used vendor specific UUID. */ + + +/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_connect(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_gatts_value_t gatts_val; + uint8_t cccd_value[2]; + ble_nus_client_context_t * p_client = NULL; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gap_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gap_evt.conn_handle); + } + + /* Check the hosts CCCD value to inform of readiness to send data using the RX characteristic */ + memset(&gatts_val, 0, sizeof(ble_gatts_value_t)); + gatts_val.p_value = cccd_value; + gatts_val.len = sizeof(cccd_value); + gatts_val.offset = 0; + + err_code = sd_ble_gatts_value_get(p_ble_evt->evt.gap_evt.conn_handle, + p_nus->tx_handles.cccd_handle, + &gatts_val); + + if ((err_code == NRF_SUCCESS) && + (p_nus->data_handler != NULL) && + ble_srv_is_notification_enabled(gatts_val.p_value)) + { + if (p_client != NULL) + { + p_client->is_notification_enabled = true; + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_COMM_STARTED; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gap_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_write(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + } + + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + if ((p_evt_write->handle == p_nus->tx_handles.cccd_handle) && + (p_evt_write->len == 2)) + { + if (p_client != NULL) + { + if (ble_srv_is_notification_enabled(p_evt_write->data)) + { + p_client->is_notification_enabled = true; + evt.type = BLE_NUS_EVT_COMM_STARTED; + } + else + { + p_client->is_notification_enabled = false; + evt.type = BLE_NUS_EVT_COMM_STOPPED; + } + + if (p_nus->data_handler != NULL) + { + p_nus->data_handler(&evt); + } + + } + } + else if ((p_evt_write->handle == p_nus->rx_handles.value_handle) && + (p_nus->data_handler != NULL)) + { + evt.type = BLE_NUS_EVT_RX_DATA; + evt.params.rx_data.p_data = p_evt_write->data; + evt.params.rx_data.length = p_evt_write->len; + + p_nus->data_handler(&evt); + } + else + { + // Do Nothing. This event is not relevant for this service. + } +} + + +/**@brief Function for handling the @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event from the SoftDevice. + * + * @param[in] p_nus Nordic UART Service structure. + * @param[in] p_ble_evt Pointer to the event received from BLE stack. + */ +static void on_hvx_tx_complete(ble_nus_t * p_nus, ble_evt_t const * p_ble_evt) +{ + ret_code_t err_code; + ble_nus_evt_t evt; + ble_nus_client_context_t * p_client; + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, + p_ble_evt->evt.gatts_evt.conn_handle, + (void *) &p_client); + if (err_code != NRF_SUCCESS) + { + NRF_LOG_ERROR("Link context for 0x%02X connection handle could not be fetched.", + p_ble_evt->evt.gatts_evt.conn_handle); + return; + } + + if ((p_client->is_notification_enabled) && (p_nus->data_handler != NULL)) + { + memset(&evt, 0, sizeof(ble_nus_evt_t)); + evt.type = BLE_NUS_EVT_TX_RDY; + evt.p_nus = p_nus; + evt.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle; + evt.p_link_ctx = p_client; + + p_nus->data_handler(&evt); + } +} + + +void ble_nus_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context) +{ + if ((p_context == NULL) || (p_ble_evt == NULL)) + { + return; + } + + ble_nus_t * p_nus = (ble_nus_t *)p_context; + + switch (p_ble_evt->header.evt_id) + { + case BLE_GAP_EVT_CONNECTED: + on_connect(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_WRITE: + on_write(p_nus, p_ble_evt); + break; + + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + on_hvx_tx_complete(p_nus, p_ble_evt); + break; + + default: + // No implementation needed. + break; + } +} + + +uint32_t ble_nus_init(ble_nus_t * p_nus, ble_nus_init_t const * p_nus_init) +{ + ret_code_t err_code; + ble_uuid_t ble_uuid; + ble_uuid128_t nus_base_uuid = NUS_BASE_UUID; + ble_add_char_params_t add_char_params; + + VERIFY_PARAM_NOT_NULL(p_nus); + VERIFY_PARAM_NOT_NULL(p_nus_init); + + // Initialize the service structure. + p_nus->data_handler = p_nus_init->data_handler; + + /**@snippet [Adding proprietary Service to the SoftDevice] */ + // Add a custom base UUID. + err_code = sd_ble_uuid_vs_add(&nus_base_uuid, &p_nus->uuid_type); + VERIFY_SUCCESS(err_code); + + ble_uuid.type = p_nus->uuid_type; + ble_uuid.uuid = BLE_UUID_NUS_SERVICE; + + // Add the service. + err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, + &ble_uuid, + &p_nus->service_handle); + /**@snippet [Adding proprietary Service to the SoftDevice] */ + VERIFY_SUCCESS(err_code); + + // Add the RX Characteristic. + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_RX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_RX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.write = 1; + add_char_params.char_props.write_wo_resp = 1; + + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + + err_code = characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->rx_handles); + if (err_code != NRF_SUCCESS) + { + return err_code; + } + + // Add the TX Characteristic. + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ + memset(&add_char_params, 0, sizeof(add_char_params)); + add_char_params.uuid = BLE_UUID_NUS_TX_CHARACTERISTIC; + add_char_params.uuid_type = p_nus->uuid_type; + add_char_params.max_len = BLE_NUS_MAX_TX_CHAR_LEN; + add_char_params.init_len = sizeof(uint8_t); + add_char_params.is_var_len = true; + add_char_params.char_props.notify = 1; + + add_char_params.read_access = SEC_MITM; + add_char_params.write_access = SEC_MITM; + add_char_params.cccd_write_access = SEC_MITM; + + return characteristic_add(p_nus->service_handle, &add_char_params, &p_nus->tx_handles); + /**@snippet [Adding proprietary characteristic to the SoftDevice] */ +} + + +uint32_t ble_nus_data_send(ble_nus_t * p_nus, + uint8_t * p_data, + uint16_t * p_length, + uint16_t conn_handle) +{ + ret_code_t err_code; + ble_gatts_hvx_params_t hvx_params; + ble_nus_client_context_t * p_client; + + VERIFY_PARAM_NOT_NULL(p_nus); + + err_code = blcm_link_ctx_get(p_nus->p_link_ctx_storage, conn_handle, (void *) &p_client); + VERIFY_SUCCESS(err_code); + + if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) + { + return NRF_ERROR_NOT_FOUND; + } + + if (!p_client->is_notification_enabled) + { + return NRF_ERROR_INVALID_STATE; + } + + if (*p_length > BLE_NUS_MAX_DATA_LEN) + { + return NRF_ERROR_INVALID_PARAM; + } + + memset(&hvx_params, 0, sizeof(hvx_params)); + + hvx_params.handle = p_nus->tx_handles.value_handle; + hvx_params.p_data = p_data; + hvx_params.p_len = p_length; + hvx_params.type = BLE_GATT_HVX_NOTIFICATION; + + return sd_ble_gatts_hvx(conn_handle, &hvx_params); +} + + +#endif // NRF_MODULE_ENABLED(BLE_NUS) diff --git a/core/embed/ble_firmware/connection.c b/core/embed/ble_firmware/connection.c new file mode 100644 index 000000000..87d20f359 --- /dev/null +++ b/core/embed/ble_firmware/connection.c @@ -0,0 +1,17 @@ + +#include "ble_gap.h" + +#include "connection.h" + +static uint16_t m_conn_handle = + BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */ + +void set_connection_handle(uint16_t val) { m_conn_handle = val; } +uint16_t get_connection_handle(void) { return m_conn_handle; } + +void disconnect(void) { + if (m_conn_handle != BLE_CONN_HANDLE_INVALID) { + sd_ble_gap_disconnect(m_conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + } +} diff --git a/core/embed/ble_firmware/connection.h b/core/embed/ble_firmware/connection.h new file mode 100644 index 000000000..7eecbdf50 --- /dev/null +++ b/core/embed/ble_firmware/connection.h @@ -0,0 +1,11 @@ +#ifndef BLE_CONNECTION_H__ +#define BLE_CONNECTION_H__ + +#include + +void set_connection_handle(uint16_t val); +uint16_t get_connection_handle(void); + +void disconnect(void); + +#endif diff --git a/core/embed/ble_firmware/defs.h b/core/embed/ble_firmware/defs.h new file mode 100644 index 000000000..b2e354d3c --- /dev/null +++ b/core/embed/ble_firmware/defs.h @@ -0,0 +1,3 @@ + +#define APP_BLE_CONN_CFG_TAG \ + 1 /**< A tag identifying the SoftDevice BLE configuration. */ diff --git a/core/embed/ble_firmware/dis.c b/core/embed/ble_firmware/dis.c new file mode 100644 index 000000000..0d4a673bb --- /dev/null +++ b/core/embed/ble_firmware/dis.c @@ -0,0 +1,23 @@ +#include "dis.h" +#include +#include "app_error.h" +#include "ble_dis.h" +#include "sdk_errors.h" + +#define MANUFACTURER_NAME \ + "SatoshiLabs" /**< Manufacturer. Will be passed to Device Information \ + Service. */ + +void dis_init(void) { + ret_code_t err_code; + ble_dis_init_t dis_init_obj; + + memset(&dis_init_obj, 0, sizeof(dis_init_obj)); + + ble_srv_ascii_to_utf8(&dis_init_obj.manufact_name_str, MANUFACTURER_NAME); + + dis_init_obj.dis_char_rd_sec = SEC_JUST_WORKS; + + err_code = ble_dis_init(&dis_init_obj); + APP_ERROR_CHECK(err_code); +} diff --git a/core/embed/ble_firmware/dis.h b/core/embed/ble_firmware/dis.h new file mode 100644 index 000000000..ad88ffd9a --- /dev/null +++ b/core/embed/ble_firmware/dis.h @@ -0,0 +1,6 @@ +#ifndef __DIS__ +#define __DIS__ + +void dis_init(void); + +#endif diff --git a/core/embed/ble_firmware/int_comm.c b/core/embed/ble_firmware/int_comm.c new file mode 100644 index 000000000..c6d9939fa --- /dev/null +++ b/core/embed/ble_firmware/int_comm.c @@ -0,0 +1,596 @@ +#include "int_comm.h" +#include "advertising.h" +#include "app_error.h" +#include "app_timer.h" +#include "app_uart.h" +#include "ble/int_comm_defs.h" +#include "ble_advertising.h" +#include "ble_nus.h" +#include "connection.h" +#include "messages.pb.h" +#include "nrf_dfu_types.h" +#include "nrf_drv_spi.h" +#include "nrf_gpio.h" +#include "nrf_log.h" +#include "pm.h" +#include "protob_helpers.h" +#include "stdint.h" +#include "trezor_t3w1_d1_NRF.h" + +#define SPI_INSTANCE 0 /**< SPI instance index. */ + +static uint8_t m_uart_rx_data[BLE_NUS_MAX_DATA_LEN]; +static uint8_t m_spi_tx_data[BLE_PACKET_SIZE]; +static volatile bool m_uart_rx_data_ready_internal = false; +static volatile bool m_internal_msg_ack = false; + +BLE_NUS_DEF(m_nus, + NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ + +static const nrf_drv_spi_t spi = + NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */ +static volatile bool spi_xfer_done = true; /**< Flag used to indicate that SPI + instance completed the transfer. */ + +#define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS * sizeof(uint32_t)) +#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE) +uint8_t m_dfu_settings_buffer[BOOTLOADER_SETTINGS_PAGE_SIZE] + __attribute__((section(".bootloader_settings_page"))) __attribute__((used)); + +APP_TIMER_DEF(m_backoff_timer); /**< Back off timer */ + +/** + * @brief SPI user event handler. + * @param event + */ +void spi_event_handler(nrf_drv_spi_evt_t const *p_event, void *p_context) { + spi_xfer_done = true; + NRF_LOG_INFO("Transfer completed."); +} + +static void backoff_timer_evt_handler(void *p_context) { + *(uint32_t *)p_context = 1; +} + +void int_comm_init(void) { + app_timer_create(&m_backoff_timer, APP_TIMER_MODE_SINGLE_SHOT, + backoff_timer_evt_handler); + + nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG; + spi_config.ss_pin = SPI_SS_PIN; + spi_config.miso_pin = SPI_MISO_PIN; + spi_config.mosi_pin = SPI_MOSI_PIN; + spi_config.sck_pin = SPI_SCK_PIN; + spi_config.frequency = NRF_DRV_SPI_FREQ_8M; + APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL)); +} + +void nus_init() { + uint32_t err_code; + + ble_nus_init_t nus_init; + + memset(&nus_init, 0, sizeof(nus_init)); + + nus_init.data_handler = nus_data_handler; + + err_code = ble_nus_init(&m_nus, &nus_init); + APP_ERROR_CHECK(err_code); +} + +void send_byte(uint8_t byte) { + uint32_t err_code; + + do { + err_code = app_uart_put(byte); + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY)) { + NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code); + } + } while (err_code == NRF_ERROR_BUSY); +} + +void send_packet(uint8_t message_type, const uint8_t *tx_data, uint16_t len) { + uint16_t total_len = len + OVERHEAD_SIZE; + send_byte(message_type); + send_byte((total_len >> 8) & 0xFF); + send_byte(total_len & 0xFF); + for (uint32_t i = 0; i < len; i++) { + send_byte(tx_data[i]); + } + send_byte(EOM); +} + +bool write_resp(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) { + write_state *state = (write_state *)(stream->state); + + size_t written = 0; + // while we have data left + while (written < count) { + size_t remaining = count - written; + // if all remaining data fit into our packet + if (state->packet_pos + remaining <= USB_PACKET_SIZE) { + // append data from buf to state->buf + memcpy(state->buf + state->packet_pos, buf + written, remaining); + // advance position + state->packet_pos += remaining; + // and return + return true; + } else { + // append data that fits + memcpy(state->buf + state->packet_pos, buf + written, + USB_PACKET_SIZE - state->packet_pos); + written += USB_PACKET_SIZE - state->packet_pos; + + uint32_t err_code; + // send packet + do { + uint16_t length = USB_PACKET_SIZE; + err_code = ble_nus_data_send(&m_nus, state->buf, &length, + get_connection_handle()); + if ((err_code != NRF_ERROR_INVALID_STATE) && + (err_code != NRF_ERROR_RESOURCES) && + (err_code != NRF_ERROR_NOT_FOUND)) { + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_RESOURCES); + + // prepare new packet + state->packet_index++; + memset(state->buf, 0, USB_PACKET_SIZE); + state->buf[0] = '?'; + state->packet_pos = MSG_HEADER2_LEN; + } + } + + return true; +}; + +void write_resp_flush(write_state *state) { + // if packet is not filled up completely + if (state->packet_pos < USB_PACKET_SIZE) { + // pad it with zeroes + memset(state->buf + state->packet_pos, 0, + USB_PACKET_SIZE - state->packet_pos); + } + // send packet + uint32_t err_code; + // send packet + do { + uint16_t length = USB_PACKET_SIZE; + err_code = + ble_nus_data_send(&m_nus, state->buf, &length, get_connection_handle()); + if ((err_code != NRF_ERROR_INVALID_STATE) && + (err_code != NRF_ERROR_RESOURCES) && + (err_code != NRF_ERROR_NOT_FOUND)) { + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_RESOURCES); +} + +bool write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) { + write_state *state = (write_state *)(stream->state); + + size_t written = 0; + // while we have data left + while (written < count) { + size_t remaining = count - written; + // if all remaining data fit into our packet + if (state->packet_pos + remaining <= USB_PACKET_SIZE) { + // append data from buf to state->buf + memcpy(state->buf + state->packet_pos, buf + written, remaining); + // advance position + state->packet_pos += remaining; + // and return + return true; + } else { + // append data that fits + memcpy(state->buf + state->packet_pos, buf + written, + USB_PACKET_SIZE - state->packet_pos); + written += USB_PACKET_SIZE - state->packet_pos; + + // send packet + send_packet(state->iface_num, state->buf, USB_PACKET_SIZE); + + // prepare new packet + state->packet_index++; + memset(state->buf, 0, USB_PACKET_SIZE); + state->buf[0] = '?'; + state->packet_pos = MSG_HEADER2_LEN; + } + } + + return true; +}; + +void write_flush(write_state *state) { + // if packet is not filled up completely + if (state->packet_pos < USB_PACKET_SIZE) { + // pad it with zeroes + memset(state->buf + state->packet_pos, 0, + USB_PACKET_SIZE - state->packet_pos); + } + // send packet + send_packet(state->iface_num, state->buf, USB_PACKET_SIZE); +} + +/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */ +static bool read(pb_istream_t *stream, uint8_t *buf, size_t count) { + read_state *state = (read_state *)(stream->state); + + size_t read = 0; + // while we have data left + while (read < count) { + size_t remaining = count - read; + // if all remaining data fit into our packet + if (state->packet_pos + remaining <= state->packet_size) { + // append data from buf to state->buf + memcpy(buf + read, state->buf + state->packet_pos, remaining); + // advance position + state->packet_pos += remaining; + // and return + return true; + } else { + // append data that fits + memcpy(buf + read, state->buf + state->packet_pos, + state->packet_size - state->packet_pos); + read += state->packet_size - state->packet_pos; + // read next packet + + while (!m_uart_rx_data_ready_internal) + ; + m_uart_rx_data_ready_internal = false; + memcpy(state->buf, m_uart_rx_data, USB_PACKET_SIZE); + + // prepare next packet + state->packet_index++; + state->packet_pos = MSG_HEADER2_LEN; + } + } + + return true; +} + +static void read_flush(read_state *state) { (void)state; } + +#define MSG_SEND_NRF(msg) (MSG_SEND(msg, write, write_flush)) +#define MSG_SEND_NRF_RESPONSE(msg) (MSG_SEND(msg, write_resp, write_resp_flush)) + +void process_command(uint8_t *data, uint16_t len) { + uint8_t cmd = data[0]; + switch (cmd) { + case INTERNAL_CMD_SEND_STATE: + send_status_event(); + break; + case INTERNAL_CMD_ADVERTISING_ON: + advertising_start(data[1] != 0); + send_status_event(); + break; + case INTERNAL_CMD_ADVERTISING_OFF: + advertising_stop(); + send_status_event(); + break; + case INTERNAL_CMD_ERASE_BONDS: + delete_bonds(); + send_success_event(); + break; + case INTERNAL_CMD_DISCONNECT: + disconnect(); + send_success_event(); + case INTERNAL_CMD_ACK: + m_internal_msg_ack = true; + break; + default: + break; + } +} + +secbool process_auth_key(uint8_t *data, uint32_t len, void *msg) { + recv_protob_msg(INTERNAL_MESSAGE, len, data, AuthKey_fields, msg, read, + read_flush, USB_PACKET_SIZE); + return sectrue; +} + +secbool process_success(uint8_t *data, uint32_t len, void *msg) { + recv_protob_msg(INTERNAL_MESSAGE, len, data, Success_fields, msg, read, + read_flush, USB_PACKET_SIZE); + return sectrue; +} + +void process_unexpected(uint8_t *data, uint32_t len) {} + +void prepare_response_wait(void) { + m_internal_msg_ack = false; + m_uart_rx_data_ready_internal = 0; + memset(m_uart_rx_data, 0, sizeof(m_uart_rx_data)); +} + +secbool await_response(uint16_t expected, + secbool (*process)(uint8_t *data, uint32_t len, + void *msg), + void *msg_recv) { + uint32_t timeout = 0; + + app_timer_start(m_backoff_timer, APP_TIMER_TICKS(1000), &timeout); + + while (!m_internal_msg_ack) { + if (timeout != 0 || nrf_gpio_pin_read(GPIO_3_PIN) == 0) { + app_timer_stop(m_backoff_timer); + return secfalse; + } + } + + app_timer_stop(m_backoff_timer); + + while (!m_uart_rx_data_ready_internal) { + if (nrf_gpio_pin_read(GPIO_3_PIN) == 0) { + return secfalse; + } + } + + m_uart_rx_data_ready_internal = false; + + uint16_t id = 0; + uint32_t msg_size = 0; + + msg_parse_header(m_uart_rx_data, &id, &msg_size); + + if (id == expected) { + if (process != NULL) { + return process(m_uart_rx_data, msg_size, msg_recv); + } + return sectrue; + } else { + process_unexpected(m_uart_rx_data, msg_size); + } + return secfalse; +} + +/**@brief Function for handling app_uart events. + * + * @details This function will receive a single character from the app_uart + * module and append it to a string. The string will be be sent over BLE when + * the last character received was a 'new line' '\n' (hex 0x0A) or if the string + * has reached the maximum data length. + */ +/**@snippet [Handling the data received over UART] */ +void uart_event_handle(app_uart_evt_t *p_event) { + static uint8_t index = 0; + static uint8_t message_type = 0; + static uint16_t len = 0; + uint32_t err_code; + uint8_t rx_byte = 0; + + switch (p_event->evt_type) { + case APP_UART_DATA_READY: + while (app_uart_get(&rx_byte) == NRF_SUCCESS) { + if (index == 0) { + if (rx_byte == INTERNAL_MESSAGE || rx_byte == INTERNAL_EVENT || + rx_byte == EXTERNAL_MESSAGE) { + message_type = rx_byte; + index += 1; + continue; + } else { + // unknown message + continue; + } + } + + if (index == 1) { + // len HI + len = rx_byte << 8; + index += 1; + continue; + } + + if (index == 2) { + // len LO + len |= rx_byte; + index += 1; + if (len > sizeof(m_uart_rx_data) + OVERHEAD_SIZE) { + // message too long + index = 0; + continue; + } + continue; + } + + if (index < (len - 1)) { + // command + m_uart_rx_data[index - COMM_HEADER_SIZE] = rx_byte; + index += 1; + continue; + } + + if (index >= (len - 1)) { + if (rx_byte == EOM) { + if (message_type == EXTERNAL_MESSAGE) { + NRF_LOG_DEBUG("Ready to send data over BLE NUS"); + NRF_LOG_HEXDUMP_DEBUG(m_uart_rx_data, index); + + do { + uint16_t length = (uint16_t)len - OVERHEAD_SIZE; + err_code = ble_nus_data_send(&m_nus, m_uart_rx_data, &length, + get_connection_handle()); + if ((err_code != NRF_ERROR_INVALID_STATE) && + (err_code != NRF_ERROR_RESOURCES) && + (err_code != NRF_ERROR_NOT_FOUND)) { + APP_ERROR_CHECK(err_code); + } + } while (err_code == NRF_ERROR_RESOURCES); + } else if (message_type == INTERNAL_MESSAGE) { + m_uart_rx_data_ready_internal = true; + } else if (message_type == INTERNAL_EVENT) { + process_command(m_uart_rx_data, len - OVERHEAD_SIZE); + } + } + index = 0; + } + } + break; + default: + break; + } +} +/**@snippet [Handling the data received over UART] */ + +/**@brief Function for handling the data from the Nordic UART Service. + * + * @details This function will process the data received from the Nordic UART + * BLE Service and forward it to Trezor + * + * @param[in] p_evt Nordic UART Service event. + */ +/**@snippet [Handling the data received over BLE] */ +void nus_data_handler(ble_nus_evt_t *p_evt) { + if (!nrf_gpio_pin_read(GPIO_3_PIN)) { + // communication with trezor is disabled + uint8_t iface_num = 0; + + MSG_SEND_INIT(Failure); + MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); + + msg_send.has_message = true; + memset(msg_send.message, 0, sizeof(msg_send.message)); + const char msg[] = "Device Locked or Busy"; + strncpy(msg_send.message, msg, sizeof(msg_send.message) - 1); + MSG_SEND_NRF_RESPONSE(Failure); + + return; + } + + if (p_evt->type == BLE_NUS_EVT_RX_DATA) { + NRF_LOG_DEBUG("Received data from BLE NUS. Forwarding."); + NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, + p_evt->params.rx_data.length); + + if (p_evt->params.rx_data.length != BLE_PACKET_SIZE) { + return; + } + + while (!spi_xfer_done) + ; + spi_xfer_done = false; + + memcpy(m_spi_tx_data, p_evt->params.rx_data.p_data, BLE_PACKET_SIZE); + + nrf_drv_spi_transfer(&spi, m_spi_tx_data, BLE_PACKET_SIZE, NULL, 0); + } +} +/**@snippet [Handling the data received over BLE] */ + +void send_status_event(void) { + ble_version_t version = {0}; + nrf_dfu_settings_t *settins = (nrf_dfu_settings_t *)m_dfu_settings_buffer; + + sd_ble_version_get(&version); + + event_status_msg_t msg = {0}; + msg.msg_id = INTERNAL_EVENT_STATUS; + msg.connected = (get_connection_handle() != BLE_CONN_HANDLE_INVALID) ? 1 : 0; + msg.advertising = is_advertising() ? 1 : 0; + msg.advertising_whitelist = is_advertising_wl() ? 1 : 0; + msg.peer_count = pm_peer_count(); + msg.sd_version_number = version.version_number; + msg.sd_company_id = version.company_id; + msg.sd_subversion_number = version.subversion_number; + msg.app_version = settins->app_version; + msg.bld_version = settins->bootloader_version; + + send_packet(INTERNAL_EVENT, (uint8_t *)&msg, sizeof(msg)); +} + +void send_success_event(void) { + uint8_t tx_data[] = { + INTERNAL_EVENT_SUCCESS, + }; + send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data)); +} + +uint16_t get_message_type(const uint8_t *rx_data) { + return (rx_data[3] << 8) | rx_data[4]; +} + +static bool read_authkey(pb_istream_t *stream, const pb_field_t *field, + void **arg) { + uint8_t *key_buffer = (uint8_t *)(*arg); + + if (stream->bytes_left > BLE_GAP_PASSKEY_LEN) { + return false; + } + + memset(key_buffer, 0, BLE_GAP_PASSKEY_LEN); + + while (stream->bytes_left) { + // read data + if (!pb_read(stream, (pb_byte_t *)(key_buffer), + (stream->bytes_left > BLE_GAP_PASSKEY_LEN) + ? BLE_GAP_PASSKEY_LEN + : stream->bytes_left)) { + return false; + } + } + + return true; +} + +static bool write_authkey(pb_ostream_t *stream, const pb_field_t *field, + void *const *arg) { + uint8_t *key = (uint8_t *)(*arg); + if (!pb_encode_tag_for_field(stream, field)) return false; + + return pb_encode_string(stream, (uint8_t *)key, BLE_GAP_PASSKEY_LEN); +} + +bool send_comparison_request(uint8_t *p_key, int8_t p_key_len) { + prepare_response_wait(); + uint8_t iface_num = INTERNAL_MESSAGE; + MSG_SEND_INIT(ComparisonRequest); + MSG_SEND_CALLBACK(key, write_authkey, p_key); + MSG_SEND_NRF(ComparisonRequest); + + MSG_RECV_INIT(Success); + secbool result = await_response(MessageType_MessageType_Success, + process_success, &msg_recv); + + if (result != sectrue) { + return false; + } + + return true; +} + +bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len) { + prepare_response_wait(); + uint8_t iface_num = INTERNAL_MESSAGE; + MSG_SEND_INIT(PairingRequest); + MSG_SEND_NRF(PairingRequest); + + uint8_t buffer[BLE_GAP_PASSKEY_LEN]; + MSG_RECV_INIT(AuthKey); + MSG_RECV_CALLBACK(key, read_authkey, buffer); + secbool result = await_response(MessageType_MessageType_AuthKey, + process_auth_key, &msg_recv); + + if (result != sectrue) { + return false; + } + + memcpy(p_key, buffer, + BLE_GAP_PASSKEY_LEN > p_key_len ? p_key_len : BLE_GAP_PASSKEY_LEN); + + return true; +} + +bool send_repair_request(void) { + prepare_response_wait(); + uint8_t iface_num = INTERNAL_MESSAGE; + MSG_SEND_INIT(RepairRequest); + MSG_SEND_NRF(RepairRequest); + + MSG_RECV_INIT(Success); + + secbool result = await_response(MessageType_MessageType_Success, + process_success, &msg_recv); + + return result == sectrue; +} diff --git a/core/embed/ble_firmware/int_comm.h b/core/embed/ble_firmware/int_comm.h new file mode 100644 index 000000000..a09c2c4b2 --- /dev/null +++ b/core/embed/ble_firmware/int_comm.h @@ -0,0 +1,27 @@ +#ifndef __INT_COMM__ +#define __INT_COMM__ + +#include "app_uart.h" +#include "ble_nus.h" +#include "stdint.h" + +void int_comm_init(void); + +void nus_init(void); + +void nus_data_handler(ble_nus_evt_t *p_evt); + +void uart_event_handle(app_uart_evt_t *p_event); + +void send_status_event(void); +void send_success_event(void); + +bool send_comparison_request(uint8_t *p_key, int8_t p_key_len); + +bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len); + +bool send_repair_request(void); + +void send_initialized(void); + +#endif diff --git a/core/embed/ble_firmware/jlink.jdebug b/core/embed/ble_firmware/jlink.jdebug new file mode 100644 index 000000000..8e6976c84 --- /dev/null +++ b/core/embed/ble_firmware/jlink.jdebug @@ -0,0 +1,332 @@ +/********************************************************************* +* (c) SEGGER Microcontroller GmbH * +* The Embedded Experts * +* www.segger.com * +********************************************************************** + +File : /home/mbruna/CLionProjects/trezor-model_r/core/embed/ble_firmware/jlink.jdebug +Created : 6 Feb 2023 15:54 +Ozone Version : V3.28c +*/ + +/********************************************************************* +* +* OnProjectLoad +* +* Function description +* Project load routine. Required. +* +********************************************************************** +*/ +void OnProjectLoad (void) { + // + // Dialog-generated settings + // + Project.AddPathSubstitute (".", "$(ProjectDir)"); + Project.AddPathSubstitute (".", "$(ProjectDir)"); + Project.SetDevice ("Cortex-M4"); + Project.SetHostIF ("USB", ""); + Project.SetTargetIF ("SWD"); + Project.SetTIFSpeed ("20 MHz"); + Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd"); + // + // User settings + // + File.Open ("../../build/ble_firmware/ble_firmware.elf"); +} + +/********************************************************************* +* +* OnStartupComplete +* +* Function description +* Called when program execution has reached/passed +* the startup completion point. Optional. +* +********************************************************************** +*/ +//void OnStartupComplete (void) { +//} + +/********************************************************************* +* +* TargetReset +* +* Function description +* Replaces the default target device reset routine. Optional. +* +* Notes +* This example demonstrates the usage when +* debugging an application in RAM on a Cortex-M target device. +* +********************************************************************** +*/ +//void TargetReset (void) { +// +// unsigned int SP; +// unsigned int PC; +// unsigned int VectorTableAddr; +// +// VectorTableAddr = Elf.GetBaseAddr(); +// // +// // Set up initial stack pointer +// // +// if (VectorTableAddr != 0xFFFFFFFF) { +// SP = Target.ReadU32(VectorTableAddr); +// Target.SetReg("SP", SP); +// } +// // +// // Set up entry point PC +// // +// PC = Elf.GetEntryPointPC(); +// +// if (PC != 0xFFFFFFFF) { +// Target.SetReg("PC", PC); +// } else if (VectorTableAddr != 0xFFFFFFFF) { +// PC = Target.ReadU32(VectorTableAddr + 4); +// Target.SetReg("PC", PC); +// } else { +// Util.Error("Project file error: failed to set entry point PC", 1); +// } +//} + +/********************************************************************* +* +* BeforeTargetReset +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetReset (void) { +//} + +/********************************************************************* +* +* AfterTargetReset +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +** +********************************************************************** +*/ +void AfterTargetReset (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* DebugStart +* +* Function description +* Replaces the default debug session startup routine. Optional. +* +********************************************************************** +*/ +//void DebugStart (void) { +//} + +/********************************************************************* +* +* TargetConnect +* +* Function description +* Replaces the default target IF connection routine. Optional. +* +********************************************************************** +*/ +//void TargetConnect (void) { +//} + +/********************************************************************* +* +* BeforeTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +void BeforeTargetConnect (void) { + Project.SetJLinkScript("./MMDScript.JLinkScript"); +} + +/********************************************************************* +* +* AfterTargetConnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetConnect (void) { +//} + +/********************************************************************* +* +* TargetDownload +* +* Function description +* Replaces the default program download routine. Optional. +* +********************************************************************** +*/ +//void TargetDownload (void) { +//} + +/********************************************************************* +* +* BeforeTargetDownload +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDownload (void) { +//} + +/********************************************************************* +* +* AfterTargetDownload +* +* Function description +* Event handler routine. Optional. +* The default implementation initializes SP and PC to reset values. +* +********************************************************************** +*/ +void AfterTargetDownload (void) { + _SetupTarget(); +} + +/********************************************************************* +* +* BeforeTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetDisconnect +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetDisconnect (void) { +//} + +/********************************************************************* +* +* AfterTargetHalt +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void AfterTargetHalt (void) { +//} + +/********************************************************************* +* +* BeforeTargetResume +* +* Function description +* Event handler routine. Optional. +* +********************************************************************** +*/ +//void BeforeTargetResume (void) { +//} + +/********************************************************************* +* +* OnSnapshotLoad +* +* Function description +* Called upon loading a snapshot. Optional. +* +* Additional information +* This function is used to restore the target state in cases +* where values cannot simply be written to the target. +* Typical use: GPIO clock needs to be enabled, before +* GPIO is configured. +* +********************************************************************** +*/ +//void OnSnapshotLoad (void) { +//} + +/********************************************************************* +* +* OnSnapshotSave +* +* Function description +* Called upon saving a snapshot. Optional. +* +* Additional information +* This function is usually used to save values of the target +* state which can either not be trivially read, +* or need to be restored in a specific way or order. +* Typically use: Memory Mapped Registers, +* such as PLL and GPIO configuration. +* +********************************************************************** +*/ +//void OnSnapshotSave (void) { +//} + +/********************************************************************* +* +* OnError +* +* Function description +* Called when an error ocurred. Optional. +* +********************************************************************** +*/ +//void OnError (void) { +//} + +/********************************************************************* +* +* AfterProjectLoad +* +* Function description +* After Project load routine. Optional. +* +********************************************************************** +*/ +//void AfterProjectLoad (void) { +//} + +/********************************************************************* +* +* _SetupTarget +* +* Function description +* Setup the target. +* Called by AfterTargetReset() and AfterTargetDownload(). +* +* Auto-generated function. May be overridden by Ozone. +* +********************************************************************** +*/ +void _SetupTarget(void) { + // + // this function is intentionally empty because both inital PC and + // initial SP were chosen not to be set + // +} diff --git a/core/embed/ble_firmware/main.c b/core/embed/ble_firmware/main.c new file mode 100644 index 000000000..05e672c62 --- /dev/null +++ b/core/embed/ble_firmware/main.c @@ -0,0 +1,627 @@ +/** + * Copyright (c) 2014 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be + * reverse engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** @file + * + * @defgroup ble_sdk_uart_over_ble_main main.c + * @{ + * @ingroup ble_sdk_app_nus_eval + * @brief UART over BLE application main file. + * + * This file contains the source code for a sample application that uses the + * Nordic UART service. This application uses the @ref srvlib_conn_params + * module. + */ + +#include +#include +#include "app_scheduler.h" +#include "app_timer.h" +#include "app_uart.h" +#include "app_util_platform.h" +#include "ble_conn_params.h" +#include "ble_hci.h" +#include "nordic_common.h" +#include "nrf.h" +#include "nrf_ble_gatt.h" +#include "nrf_ble_qwr.h" +#include "nrf_drv_uart.h" +#include "nrf_gpio.h" +#include "nrf_pwr_mgmt.h" +#include "nrf_sdh.h" +#include "nrf_sdh_ble.h" +#include "nrf_sdh_soc.h" +#include "trezor_t3w1_d1_NRF.h" + +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#endif + +#if defined(UART_PRESENT) +#include "nrf_uart.h" +#endif +#if defined(UARTE_PRESENT) +#include "nrf_uarte.h" +#endif + +#include "nrf_log.h" +#include "nrf_log_ctrl.h" +#include "nrf_log_default_backends.h" + +#include "advertising.h" +#include "ble_nus.h" +#include "connection.h" +#include "defs.h" +#include "dis.h" +#include "int_comm.h" +#include "nrf_ble_lesc.h" +#include "pm.h" +#include "power.h" + +#define DEVICE_NAME \ + "Trezor" /**< Name of device. Will be included in the advertising data. \ + */ + +#define APP_BLE_OBSERVER_PRIO \ + 3 /**< Application's BLE observer priority. You shouldn't need to modify \ + this value. */ + +#define MIN_CONN_INTERVAL \ + MSEC_TO_UNITS( \ + 7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), \ + Connection interval uses 1.25 ms units. */ +#define MAX_CONN_INTERVAL \ + MSEC_TO_UNITS( \ + 7.5, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), \ + Connection interval uses 1.25 ms units. */ +#define SLAVE_LATENCY 0 /**< Slave latency. */ +#define CONN_SUP_TIMEOUT \ + MSEC_TO_UNITS(4000, \ + UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), \ + Supervision Timeout uses 10 ms units. */ +#define FIRST_CONN_PARAMS_UPDATE_DELAY \ + APP_TIMER_TICKS( \ + 5000) /**< Time from initiating event (connect or start of notification) \ + to first time sd_ble_gap_conn_param_update is called (5 \ + seconds). */ +#define NEXT_CONN_PARAMS_UPDATE_DELAY \ + APP_TIMER_TICKS( \ + 30000) /**< Time between each call to sd_ble_gap_conn_param_update after \ + the first call (30 seconds). */ +#define MAX_CONN_PARAMS_UPDATE_COUNT \ + 3 /**< Number of attempts before giving up the connection parameter \ + negotiation. */ + +#define DEAD_BEEF \ + 0xDEADBEEF /**< Value used as error code on stack dump, can be used to \ + identify stack location on stack unwind. */ + +#define UART_TX_BUF_SIZE 256 /**< UART TX buffer size. */ +#define UART_RX_BUF_SIZE 256 /**< UART RX buffer size. */ + +NRF_BLE_GATT_DEF(m_gatt); /**< GATT module instance. */ +NRF_BLE_QWR_DEF(m_qwr); /**< Context for the Queued Write module.*/ + +#define SCHED_MAX_EVENT_DATA_SIZE \ + APP_TIMER_SCHED_EVENT_DATA_SIZE /**< Maximum size of scheduler events. */ +#ifdef SVCALL_AS_NORMAL_FUNCTION +#define SCHED_QUEUE_SIZE \ + 20 /**< Maximum number of events in the scheduler queue. More is needed in \ + case of Serialization. */ +#else +#define SCHED_QUEUE_SIZE \ + 10 /**< Maximum number of events in the scheduler queue. */ +#endif + +static uint16_t m_ble_nus_max_data_len = + BLE_GATT_ATT_MTU_DEFAULT - + 3; /**< Maximum length of data (in bytes) that can be transmitted to the + peer by the Nordic UART service module. */ + +/**@brief Function for assert macro callback. + * + * @details This function will be called in case of an assert in the SoftDevice. + * + * @warning On assert from the SoftDevice, the system can only recover on reset. + * + * @param[in] line_num Line number of the failing ASSERT call. + * @param[in] p_file_name File name of the failing ASSERT call. + */ +void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) { + app_error_handler(DEAD_BEEF, line_num, p_file_name); +} + +/*lint -save -e14 */ +/** + * Function is implemented as weak so that it can be overwritten by custom + * application error handler when needed. + */ +void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) { + __disable_irq(); + + // signalize firmware not running + nrf_gpio_pin_clear(GPIO_2_PIN); + + NRF_LOG_FINAL_FLUSH(); + +#ifndef DEBUG + NRF_LOG_ERROR("Fatal error"); +#else + switch (id) { +#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT + case NRF_FAULT_ID_SD_ASSERT: + NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED"); + break; + case NRF_FAULT_ID_APP_MEMACC: + NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS"); + break; +#endif + case NRF_FAULT_ID_SDK_ASSERT: { + assert_info_t *p_info = (assert_info_t *)info; + NRF_LOG_ERROR("ASSERTION FAILED at %s:%u", p_info->p_file_name, + p_info->line_num); + break; + } + case NRF_FAULT_ID_SDK_ERROR: { + error_info_t *p_info = (error_info_t *)info; + NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x", p_info->err_code, + nrf_strerror_get(p_info->err_code), p_info->p_file_name, + p_info->line_num, pc); + NRF_LOG_ERROR("End of error report"); + break; + } + default: + NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc); + break; + } +#endif + + NRF_BREAKPOINT_COND; + // On assert, the system can only recover with a reset. + +#ifndef DEBUG + NRF_LOG_WARNING("System reset"); + NVIC_SystemReset(); +#else + app_error_save_and_stop(id, pc, info); +#endif // DEBUG +} + +/**@brief Function for initializing the timer module. + */ +static void timers_init(void) { + ret_code_t err_code = app_timer_init(); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for the GAP initialization. + * + * @details This function will set up all the necessary GAP (Generic Access + * Profile) parameters of the device. It also sets the permissions and + * appearance. + */ +static void gap_params_init(void) { + uint32_t err_code; + ble_gap_conn_params_t gap_conn_params; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)DEVICE_NAME, + strlen(DEVICE_NAME)); + APP_ERROR_CHECK(err_code); + + err_code = sd_ble_gap_appearance_set(BLE_APPEARANCE_UNKNOWN); + APP_ERROR_CHECK(err_code); + + memset(&gap_conn_params, 0, sizeof(gap_conn_params)); + + gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL; + gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL; + gap_conn_params.slave_latency = SLAVE_LATENCY; + gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT; + + err_code = sd_ble_gap_ppcp_set(&gap_conn_params); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling Queued Write Module errors. + * + * @details A pointer to this function will be passed to each service which may + * need to inform the application about an error. + * + * @param[in] nrf_error Error code containing information about what went + * wrong. + */ +static void nrf_qwr_error_handler(uint32_t nrf_error) { + APP_ERROR_HANDLER(nrf_error); +} + +/**@brief Function for initializing services that will be used by the + * application. + */ +static void services_init(void) { + uint32_t err_code; + nrf_ble_qwr_init_t qwr_init = {0}; + + // Initialize Queued Write Module. + qwr_init.error_handler = nrf_qwr_error_handler; + + err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init); + APP_ERROR_CHECK(err_code); + + dis_init(); + nus_init(); +} + +/**@brief Function for handling errors from the Connection Parameters module. + * + * @param[in] nrf_error Error code containing information about what went + * wrong. + */ +static void conn_params_error_handler(uint32_t nrf_error) { + APP_ERROR_HANDLER(nrf_error); +} + +/**@brief Function for initializing the Connection Parameters module. + */ +static void conn_params_init(void) { + uint32_t err_code; + ble_conn_params_init_t cp_init; + + memset(&cp_init, 0, sizeof(cp_init)); + + cp_init.p_conn_params = NULL; + cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY; + cp_init.next_conn_params_update_delay = NEXT_CONN_PARAMS_UPDATE_DELAY; + cp_init.max_conn_params_update_count = MAX_CONN_PARAMS_UPDATE_COUNT; + cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID; + cp_init.disconnect_on_fail = false; + cp_init.evt_handler = NULL; + cp_init.error_handler = conn_params_error_handler; + + err_code = ble_conn_params_init(&cp_init); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling BLE events. + * + * @param[in] p_ble_evt Bluetooth stack event. + * @param[in] p_context Unused. + */ +static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) { + uint32_t err_code; + char passkey[BLE_GAP_PASSKEY_LEN + 1] = {0}; + + switch (p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + NRF_LOG_INFO("Connected"); + // err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); + // APP_ERROR_CHECK(err_code); + + uint16_t handle = p_ble_evt->evt.gap_evt.conn_handle; + set_connection_handle(handle); + send_status_event(); + err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, handle); + APP_ERROR_CHECK(err_code); + break; + + case BLE_GAP_EVT_DISCONNECTED: + NRF_LOG_INFO("Disconnected"); + // bsp_indication_set(BSP_INDICATE_IDLE); + set_connection_handle(BLE_CONN_HANDLE_INVALID); + send_status_event(); + break; + + case BLE_GAP_EVT_PHY_UPDATE_REQUEST: { + NRF_LOG_DEBUG("PHY update request."); + ble_gap_phys_t const phys = { + .rx_phys = BLE_GAP_PHY_AUTO, + .tx_phys = BLE_GAP_PHY_AUTO, + }; + err_code = + sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys); + APP_ERROR_CHECK(err_code); + } break; + + case BLE_GAP_EVT_PASSKEY_DISPLAY: + memcpy(passkey, p_ble_evt->evt.gap_evt.params.passkey_display.passkey, + BLE_GAP_PASSKEY_LEN); + + NRF_LOG_INFO("BLE_GAP_EVT_PASSKEY_DISPLAY: passkey=%s match_req=%d", + nrf_log_push(passkey), + p_ble_evt->evt.gap_evt.params.passkey_display.match_request); + + if (p_ble_evt->evt.gap_evt.params.passkey_display.match_request) { + bool ok = + send_comparison_request((uint8_t *)passkey, BLE_GAP_PASSKEY_LEN); + + if (ok) { + sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, NULL); + } else { + sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_NONE, NULL); + } + } + break; + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: + NRF_LOG_INFO("BLE_GAP_EVT_LESC_DHKEY_REQUEST"); + break; + + case BLE_GAP_EVT_AUTH_KEY_REQUEST: { + NRF_LOG_INFO("Key requested."); + + bool ok = send_auth_key_request((uint8_t *)passkey, BLE_GAP_PASSKEY_LEN); + + sd_ble_gap_auth_key_reply(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_AUTH_KEY_TYPE_PASSKEY, + (uint8_t *)passkey); + + if (ok) { + NRF_LOG_INFO("Received data: %c", passkey); + } else { + NRF_LOG_INFO("Auth key request failed."); + } + + // APP_ERROR_CHECK(err_code); + break; + } + case BLE_GATTC_EVT_TIMEOUT: + // Disconnect on GATT Client timeout event. + err_code = + sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + break; + + case BLE_GATTS_EVT_TIMEOUT: + // Disconnect on GATT Server timeout event. + err_code = + sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, + BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); + APP_ERROR_CHECK(err_code); + break; + + default: + // No implementation needed. + break; + } +} + +/**@brief Function for the SoftDevice initialization. + * + * @details This function initializes the SoftDevice and the BLE event + * interrupt. + */ +static void ble_stack_init(void) { + ret_code_t err_code; + + err_code = nrf_sdh_enable_request(); + APP_ERROR_CHECK(err_code); + + // Configure the BLE stack using the default settings. + // Fetch the start address of the application RAM. + uint32_t ram_start = 0; + err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start); + APP_ERROR_CHECK(err_code); + + // Enable BLE stack. + err_code = nrf_sdh_ble_enable(&ram_start); + APP_ERROR_CHECK(err_code); + + // Register a handler for BLE events. + NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, + NULL); +} + +/**@brief Function for handling events from the GATT library. */ +void gatt_evt_handler(nrf_ble_gatt_t *p_gatt, nrf_ble_gatt_evt_t const *p_evt) { + if ((get_connection_handle() == p_evt->conn_handle) && + (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED)) { + m_ble_nus_max_data_len = + p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH; + NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, + m_ble_nus_max_data_len); + } + NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x", + p_gatt->att_mtu_desired_central, + p_gatt->att_mtu_desired_periph); +} + +/**@brief Function for initializing the GATT library. */ +void gatt_init(void) { + ret_code_t err_code; + + err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler); + APP_ERROR_CHECK(err_code); + + err_code = + nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE); + APP_ERROR_CHECK(err_code); +} + +///**@brief Function for handling events from the BSP module. +// * +// * @param[in] event Event generated by button press. +// */ +// void bsp_event_handler(bsp_event_t event) { +// uint32_t err_code; +// switch (event) { +// case BSP_EVENT_SLEEP: +// sleep_mode_enter(); +// break; +// +// case BSP_EVENT_DISCONNECT: +// err_code = sd_ble_gap_disconnect( +// get_connection_handle(), BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); +// if (err_code != NRF_ERROR_INVALID_STATE) { +// APP_ERROR_CHECK(err_code); +// } +// break; +// +// case BSP_EVENT_WHITELIST_OFF: +// if (get_connection_handle() == BLE_CONN_HANDLE_INVALID) { +// advertising_restart_without_whitelist(); +// } +// break; +// +// default: +// break; +// } +//} + +/**@brief Function for initializing the UART module. + */ +/**@snippet [UART Initialization] */ +static void uart_init(void) { + uint32_t err_code; + app_uart_comm_params_t const comm_params = { + .rx_pin_no = RX_PIN_NUMBER, + .tx_pin_no = TX_PIN_NUMBER, + .rts_pin_no = RTS_PIN_NUMBER, + .cts_pin_no = CTS_PIN_NUMBER, + .flow_control = APP_UART_FLOW_CONTROL_ENABLED, + .use_parity = false, +#if defined(UART_PRESENT) + .baud_rate = NRF_UART_BAUDRATE_1000000 +#else + .baud_rate = NRF_UARTE_BAUDRATE_1000000 +#endif + }; + + APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, + uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code); + APP_ERROR_CHECK(err_code); +} +/**@snippet [UART Initialization] */ + +///**@brief Function for initializing buttons and leds. +// * +// * @param[out] p_erase_bonds Will be true if the clear bonding button was +// * pressed to wake the application up. +// */ +// static void buttons_leds_init(bool *p_erase_bonds) { +// bsp_event_t startup_event; +// +// uint32_t err_code = +// bsp_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS, bsp_event_handler); +// APP_ERROR_CHECK(err_code); +// +// err_code = bsp_btn_ble_init(NULL, &startup_event); +// APP_ERROR_CHECK(err_code); +// +// *p_erase_bonds = (startup_event == BSP_EVENT_CLEAR_BONDING_DATA); +//} + +/**@brief Function for initializing the nrf log module. + */ +static void log_init(void) { + ret_code_t err_code = NRF_LOG_INIT(NULL); + APP_ERROR_CHECK(err_code); + + NRF_LOG_DEFAULT_BACKENDS_INIT(); +} + +/**@brief Function for initializing power management. + */ +static void power_management_init(void) { + ret_code_t err_code; + err_code = nrf_pwr_mgmt_init(); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling the idle state (main loop). + * + * @details If there is no pending log operation, then sleep until next the next + * event occurs. + */ +static void idle_state_handle(void) { + app_sched_execute(); + if (NRF_LOG_PROCESS() == false) { + nrf_pwr_mgmt_run(); + } +} + +/**@brief Function for the Event Scheduler initialization. + */ +static void scheduler_init(void) { + APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE); +} + +/**@brief Application main function. + */ +int main(void) { + nrf_gpio_cfg_output(GPIO_1_PIN); + nrf_gpio_cfg_output(GPIO_2_PIN); + nrf_gpio_cfg_input(GPIO_3_PIN, NRF_GPIO_PIN_NOPULL); + nrf_gpio_pin_clear(GPIO_1_PIN); + nrf_gpio_pin_clear(GPIO_2_PIN); + + // Initialize. + int_comm_init(); + uart_init(); + log_init(); + timers_init(); + // buttons_leds_init(&erase_bonds); + power_management_init(); + ble_stack_init(); + scheduler_init(); + gap_params_init(); + gatt_init(); + services_init(); + advertising_init(); + conn_params_init(); + peer_manager_init(); + + // signalize firmware running + nrf_gpio_pin_set(GPIO_2_PIN); + send_status_event(); + + // Enter main loop. + for (;;) { + nrf_ble_lesc_request_handler(); + idle_state_handle(); + } +} + +/** + * @} + */ diff --git a/core/embed/ble_firmware/memory.ld b/core/embed/ble_firmware/memory.ld new file mode 100644 index 000000000..245e232e1 --- /dev/null +++ b/core/embed/ble_firmware/memory.ld @@ -0,0 +1,139 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0x49000 + RAM (rwx) : ORIGIN = 0x20002ae8, LENGTH = 0x1d518 + bootloader_settings_page (r) : ORIGIN = 0x0007F000, LENGTH = 0x1000 +} + +SECTIONS +{ + . = ALIGN(4); + .bootloader_settings_page(NOLOAD) : + { + PROVIDE(__start_bootloader_settings_page = .); + KEEP(*(SORT(.bootloader_settings_page*))) + PROVIDE(__stop_bootloader_settings_page = .); + } > bootloader_settings_page + . = ALIGN(4); +} + +SECTIONS +{ + . = ALIGN(4); + .mem_section_dummy_ram : + { + } + .cli_sorted_cmd_ptrs : + { + PROVIDE(__start_cli_sorted_cmd_ptrs = .); + KEEP(*(.cli_sorted_cmd_ptrs)) + PROVIDE(__stop_cli_sorted_cmd_ptrs = .); + } > RAM + .fs_data : + { + PROVIDE(__start_fs_data = .); + KEEP(*(.fs_data)) + PROVIDE(__stop_fs_data = .); + } > RAM + .log_dynamic_data : + { + PROVIDE(__start_log_dynamic_data = .); + KEEP(*(SORT(.log_dynamic_data*))) + PROVIDE(__stop_log_dynamic_data = .); + } > RAM + .log_filter_data : + { + PROVIDE(__start_log_filter_data = .); + KEEP(*(SORT(.log_filter_data*))) + PROVIDE(__stop_log_filter_data = .); + } > RAM + +} INSERT AFTER .data; + +SECTIONS +{ + .mem_section_dummy_rom : + { + } + .sdh_soc_observers : + { + PROVIDE(__start_sdh_soc_observers = .); + KEEP(*(SORT(.sdh_soc_observers*))) + PROVIDE(__stop_sdh_soc_observers = .); + } > FLASH + .sdh_ble_observers : + { + PROVIDE(__start_sdh_ble_observers = .); + KEEP(*(SORT(.sdh_ble_observers*))) + PROVIDE(__stop_sdh_ble_observers = .); + } > FLASH + .pwr_mgmt_data : + { + PROVIDE(__start_pwr_mgmt_data = .); + KEEP(*(SORT(.pwr_mgmt_data*))) + PROVIDE(__stop_pwr_mgmt_data = .); + } > FLASH + .sdh_req_observers : + { + PROVIDE(__start_sdh_req_observers = .); + KEEP(*(SORT(.sdh_req_observers*))) + PROVIDE(__stop_sdh_req_observers = .); + } > FLASH + .sdh_state_observers : + { + PROVIDE(__start_sdh_state_observers = .); + KEEP(*(SORT(.sdh_state_observers*))) + PROVIDE(__stop_sdh_state_observers = .); + } > FLASH + .sdh_stack_observers : + { + PROVIDE(__start_sdh_stack_observers = .); + KEEP(*(SORT(.sdh_stack_observers*))) + PROVIDE(__stop_sdh_stack_observers = .); + } > FLASH + .nrf_queue : + { + PROVIDE(__start_nrf_queue = .); + KEEP(*(.nrf_queue)) + PROVIDE(__stop_nrf_queue = .); + } > FLASH + .nrf_balloc : + { + PROVIDE(__start_nrf_balloc = .); + KEEP(*(.nrf_balloc)) + PROVIDE(__stop_nrf_balloc = .); + } > FLASH + .cli_command : + { + PROVIDE(__start_cli_command = .); + KEEP(*(.cli_command)) + PROVIDE(__stop_cli_command = .); + } > FLASH + .crypto_data : + { + PROVIDE(__start_crypto_data = .); + KEEP(*(SORT(.crypto_data*))) + PROVIDE(__stop_crypto_data = .); + } > FLASH + .log_const_data : + { + PROVIDE(__start_log_const_data = .); + KEEP(*(SORT(.log_const_data*))) + PROVIDE(__stop_log_const_data = .); + } > FLASH + .log_backends : + { + PROVIDE(__start_log_backends = .); + KEEP(*(SORT(.log_backends*))) + PROVIDE(__stop_log_backends = .); + } > FLASH + +} INSERT AFTER .text + + +INCLUDE "nrf_common.ld" diff --git a/core/embed/ble_firmware/pm.c b/core/embed/ble_firmware/pm.c new file mode 100644 index 000000000..72597b83d --- /dev/null +++ b/core/embed/ble_firmware/pm.c @@ -0,0 +1,158 @@ + + +#include "nrf_log.h" +#include "peer_manager_handler.h" + +#include "int_comm.h" +#include "pm.h" + +#define SEC_PARAM_BOND 1 /**< Perform bonding. */ +#define SEC_PARAM_MITM 1 /**< Man In The Middle protection required. */ +#define SEC_PARAM_LESC 1 /**< LE Secure Connections enabled. */ +#define SEC_PARAM_KEYPRESS 0 /**< Keypress notifications not enabled. */ +#define SEC_PARAM_IO_CAPABILITIES \ + BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY /**< Display and keyboard I/O capabilities. \ + */ +#define SEC_PARAM_OOB 0 /**< Out Of Band data not available. */ +#define SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */ +#define SEC_PARAM_MAX_KEY_SIZE 16 /**< Maximum encryption key size. */ + +static pm_peer_id_t + m_peer_id; /**< Device reference handle to the current bonded central. */ + +pm_peer_id_t get_peer_id(void) { return m_peer_id; } + +/**@brief Function for setting filtered whitelist. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. + */ +void whitelist_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_WHITELIST_ADDR_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); + APP_ERROR_CHECK(err_code); + + NRF_LOG_INFO("\tm_whitelist_peer_cnt %d, MAX_PEERS_WLIST %d", + peer_id_count + 1, BLE_GAP_WHITELIST_ADDR_MAX_COUNT); + + err_code = pm_whitelist_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for handling Peer Manager events. + * + * @param[in] p_evt Peer Manager event. + */ +void pm_evt_handler(pm_evt_t const *p_evt) { + pm_handler_on_pm_evt(p_evt); + pm_handler_disconnect_on_sec_failure(p_evt); + pm_handler_flash_clean(p_evt); + + switch (p_evt->evt_id) { + case PM_EVT_CONN_SEC_SUCCEEDED: + m_peer_id = p_evt->peer_id; + break; + + case PM_EVT_PEERS_DELETE_SUCCEEDED: + send_status_event(); + break; + + case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED: + if (p_evt->params.peer_data_update_succeeded.flash_changed && + (p_evt->params.peer_data_update_succeeded.data_id == + PM_PEER_DATA_ID_BONDING)) { + NRF_LOG_INFO("New Bond, add the peer to the whitelist if possible"); + // Note: You should check on what kind of white list policy your + // application should use. + + whitelist_set(PM_PEER_ID_LIST_SKIP_NO_ID_ADDR); + send_status_event(); + } + break; + case PM_EVT_CONN_SEC_CONFIG_REQ: { + bool ok = send_repair_request(); + + if (ok) { + // Allow pairing request from an already bonded peer. + pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true}; + pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); + } else { + // Reject pairing request from an already bonded peer. + pm_conn_sec_config_t conn_sec_config = {.allow_repairing = false}; + pm_conn_sec_config_reply(p_evt->conn_handle, &conn_sec_config); + } + + } break; + default: + break; + } +} + +/**@brief Function for the Peer Manager initialization. + */ +void peer_manager_init(void) { + ble_gap_sec_params_t sec_param; + pm_privacy_params_t privacy_params; + ret_code_t err_code; + + err_code = pm_init(); + APP_ERROR_CHECK(err_code); + + memset(&sec_param, 0, sizeof(ble_gap_sec_params_t)); + + // Security parameters to be used for all security procedures. + sec_param.bond = SEC_PARAM_BOND; + sec_param.mitm = SEC_PARAM_MITM; + sec_param.lesc = SEC_PARAM_LESC; + sec_param.keypress = SEC_PARAM_KEYPRESS; + sec_param.io_caps = SEC_PARAM_IO_CAPABILITIES; + sec_param.oob = SEC_PARAM_OOB; + sec_param.min_key_size = SEC_PARAM_MIN_KEY_SIZE; + sec_param.max_key_size = SEC_PARAM_MAX_KEY_SIZE; + sec_param.kdist_own.enc = 1; + sec_param.kdist_own.id = 1; + sec_param.kdist_peer.enc = 1; + sec_param.kdist_peer.id = 1; + + err_code = pm_sec_params_set(&sec_param); + APP_ERROR_CHECK(err_code); + + privacy_params.p_device_irk = NULL; + privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_DEVICE_PRIVACY; + privacy_params.private_addr_cycle_s = 0; + privacy_params.private_addr_type = + BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE; + pm_privacy_set(&privacy_params); + + err_code = pm_register(pm_evt_handler); + APP_ERROR_CHECK(err_code); +} + +/**@brief Function for setting filtered device identities. + * + * @param[in] skip Filter passed to @ref pm_peer_id_list. + */ +void identities_set(pm_peer_id_list_skip_t skip) { + pm_peer_id_t peer_ids[BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT]; + uint32_t peer_id_count = BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT; + + ret_code_t err_code = + pm_peer_id_list(peer_ids, &peer_id_count, PM_PEER_ID_INVALID, skip); + APP_ERROR_CHECK(err_code); + + err_code = pm_device_identities_list_set(peer_ids, peer_id_count); + APP_ERROR_CHECK(err_code); +} + +/////**@brief Clear bond information from persistent storage. */ +void delete_bonds(void) { + ret_code_t err_code; + + NRF_LOG_INFO("Erase bonds!"); + + // pm_whitelist_set(NULL, 0); + err_code = pm_peers_delete(); + APP_ERROR_CHECK(err_code); +} diff --git a/core/embed/ble_firmware/pm.h b/core/embed/ble_firmware/pm.h new file mode 100644 index 000000000..cfe9e6193 --- /dev/null +++ b/core/embed/ble_firmware/pm.h @@ -0,0 +1,18 @@ +#ifndef __PEER_MANAGER__ +#define __PEER_MANAGER__ + +#include "peer_manager.h" + +pm_peer_id_t get_peer_id(void); + +void whitelist_set(pm_peer_id_list_skip_t skip); + +void identities_set(pm_peer_id_list_skip_t skip); + +/**@brief Function for the Peer Manager initialization. + */ +void peer_manager_init(void); + +void delete_bonds(void); + +#endif diff --git a/core/embed/ble_firmware/power.c b/core/embed/ble_firmware/power.c new file mode 100644 index 000000000..b6f47f016 --- /dev/null +++ b/core/embed/ble_firmware/power.c @@ -0,0 +1,21 @@ +#include "power.h" +#include "app_error.h" + +/**@brief Function for putting the chip into sleep mode. + * + * @note This function will not return. + */ +// void sleep_mode_enter(void) { +// uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE); +// APP_ERROR_CHECK(err_code); +// +// // Prepare wakeup buttons. +// err_code = bsp_btn_ble_sleep_mode_prepare(); +// APP_ERROR_CHECK(err_code); +// +// // Go to system-off mode (this function will not return; wakeup will cause +// a +// // reset). +// err_code = sd_power_system_off(); +// APP_ERROR_CHECK(err_code); +// } diff --git a/core/embed/ble_firmware/power.h b/core/embed/ble_firmware/power.h new file mode 100644 index 000000000..ac1f8965d --- /dev/null +++ b/core/embed/ble_firmware/power.h @@ -0,0 +1,6 @@ +#ifndef __POWER__ +#define __POWER__ + +void sleep_mode_enter(void); + +#endif diff --git a/core/embed/ble_firmware/sdk_config.h b/core/embed/ble_firmware/sdk_config.h new file mode 100644 index 000000000..835c6595d --- /dev/null +++ b/core/embed/ble_firmware/sdk_config.h @@ -0,0 +1,12147 @@ +// clang-format off + +/** + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form, except as embedded into a Nordic + * Semiconductor ASA integrated circuit in a product or a software update for + * such product, must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * 4. This software, with or without modification, must only be used with a + * Nordic Semiconductor ASA integrated circuit. + * + * 5. Any software provided in binary form under this license must not be reverse + * engineered, decompiled, modified and/or disassembled. + * + * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + + +#ifndef SDK_CONFIG_H +#define SDK_CONFIG_H +// <<< Use Configuration Wizard in Context Menu >>>\n +#ifdef USE_APP_CONFIG +#include "app_config.h" +#endif +// Board Support + +//========================================================== +// BSP_BTN_BLE_ENABLED - bsp_btn_ble - Button Control for BLE + + +#ifndef BSP_BTN_BLE_ENABLED +#define BSP_BTN_BLE_ENABLED 1 +#endif + +// +//========================================================== + +// nRF_BLE + +//========================================================== +// BLE_ADVERTISING_ENABLED - ble_advertising - Advertising module + + +#ifndef BLE_ADVERTISING_ENABLED +#define BLE_ADVERTISING_ENABLED 1 +#endif + +// BLE_DTM_ENABLED - ble_dtm - Module for testing RF/PHY using DTM commands +//========================================================== +#ifndef BLE_DTM_ENABLED +#define BLE_DTM_ENABLED 0 +#endif +// NRF_RADIO_ANTENNA_PIN_1 - Antenna 1 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_1 +#define NRF_RADIO_ANTENNA_PIN_1 21 +#endif + +// NRF_RADIO_ANTENNA_PIN_2 - Antenna 2 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_2 +#define NRF_RADIO_ANTENNA_PIN_2 23 +#endif + +// NRF_RADIO_ANTENNA_PIN_3 - Antenna 3 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_3 +#define NRF_RADIO_ANTENNA_PIN_3 26 +#endif + +// NRF_RADIO_ANTENNA_PIN_4 - Antenna 4 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_4 +#define NRF_RADIO_ANTENNA_PIN_4 27 +#endif + +// NRF_RADIO_ANTENNA_PIN_5 - Antenna 5 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_5 +#define NRF_RADIO_ANTENNA_PIN_5 28 +#endif + +// NRF_RADIO_ANTENNA_PIN_6 - Antenna 6 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_6 +#define NRF_RADIO_ANTENNA_PIN_6 29 +#endif + +// NRF_RADIO_ANTENNA_PIN_7 - Antenna 7 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_7 +#define NRF_RADIO_ANTENNA_PIN_7 30 +#endif + +// NRF_RADIO_ANTENNA_PIN_8 - Antenna 8 GPIO pin +#ifndef NRF_RADIO_ANTENNA_PIN_8 +#define NRF_RADIO_ANTENNA_PIN_8 31 +#endif + +// NRF_RADIO_ANTENNA_COUNT +#ifndef NRF_RADIO_ANTENNA_COUNT +#define NRF_RADIO_ANTENNA_COUNT 12 +#endif + +// DTM_RADIO_IRQ_PRIORITY - RADIO interrupt priority +#ifndef DTM_RADIO_IRQ_PRIORITY +#define DTM_RADIO_IRQ_PRIORITY 2 +#endif + +// DTM_TIMER_IRQ_PRIORITY - DTM timer interrupt priority +#ifndef DTM_TIMER_IRQ_PRIORITY +#define DTM_TIMER_IRQ_PRIORITY 3 +#endif + +// DTM_ANOMALY_172_TIMER_IRQ_PRIORITY - DTM anomaly 172 timer interrupt priority +#ifndef DTM_ANOMALY_172_TIMER_IRQ_PRIORITY +#define DTM_ANOMALY_172_TIMER_IRQ_PRIORITY 2 +#endif + +// NRF_DTM_TIMER_INSTANCE - DTM TIMER instance + +// <0=> TIMER0 +// <2=> TIMER2 +// <3=> TIMER3 +// <4=> TIMER4 + +#ifndef NRF_DTM_TIMER_INSTANCE +#define NRF_DTM_TIMER_INSTANCE 0 +#endif + +// + +// BLE_RACP_ENABLED - ble_racp - Record Access Control Point library + + +#ifndef BLE_RACP_ENABLED +#define BLE_RACP_ENABLED 0 +#endif + +// NRF_BLE_CONN_PARAMS_ENABLED - ble_conn_params - Initiating and executing a connection parameters negotiation procedure +//========================================================== +#ifndef NRF_BLE_CONN_PARAMS_ENABLED +#define NRF_BLE_CONN_PARAMS_ENABLED 1 +#endif +// NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION - The largest acceptable deviation in slave latency. +// The largest deviation (+ or -) from the requested slave latency that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SLAVE_LATENCY_DEVIATION 499 +#endif + +// NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION - The largest acceptable deviation (in 10 ms units) in supervision timeout. +// The largest deviation (+ or -, in 10 ms units) from the requested supervision timeout that will not be renegotiated. + +#ifndef NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION +#define NRF_BLE_CONN_PARAMS_MAX_SUPERVISION_TIMEOUT_DEVIATION 65535 +#endif + +// + +// NRF_BLE_GATT_ENABLED - nrf_ble_gatt - GATT module +//========================================================== +#ifndef NRF_BLE_GATT_ENABLED +#define NRF_BLE_GATT_ENABLED 1 +#endif +// NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED - Enable GATT MTU exchange initiation + + +#ifndef NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED +#define NRF_BLE_GATT_MTU_EXCHANGE_INITIATION_ENABLED 1 +#endif + +// + +// NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write) +//========================================================== +#ifndef NRF_BLE_QWR_ENABLED +#define NRF_BLE_QWR_ENABLED 1 +#endif +// NRF_BLE_QWR_MAX_ATTR - Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. If it is zero, the module will reject all Queued Write requests. +#ifndef NRF_BLE_QWR_MAX_ATTR +#define NRF_BLE_QWR_MAX_ATTR 0 +#endif + +// + +// PEER_MANAGER_ENABLED - peer_manager - Peer Manager +//========================================================== +#ifndef PEER_MANAGER_ENABLED +#define PEER_MANAGER_ENABLED 1 +#endif +// PM_MAX_REGISTRANTS - Number of event handlers that can be registered. +#ifndef PM_MAX_REGISTRANTS +#define PM_MAX_REGISTRANTS 3 +#endif + +// PM_FLASH_BUFFERS - Number of internal buffers for flash operations. +// Decrease this value to lower RAM usage. + +#ifndef PM_FLASH_BUFFERS +#define PM_FLASH_BUFFERS 4 +#endif + +// PM_CENTRAL_ENABLED - Enable/disable central-specific Peer Manager functionality. + + +// Enable/disable central-specific Peer Manager functionality. + +#ifndef PM_CENTRAL_ENABLED +#define PM_CENTRAL_ENABLED 0 +#endif + +// PM_SERVICE_CHANGED_ENABLED - Enable/disable the service changed management for GATT server in Peer Manager. + + +// If not using a GATT server, or using a server wihout a service changed characteristic, +// disable this to save code space. + +#ifndef PM_SERVICE_CHANGED_ENABLED +#define PM_SERVICE_CHANGED_ENABLED 1 +#endif + +// PM_PEER_RANKS_ENABLED - Enable/disable the peer rank management in Peer Manager. + + +// Set this to false to save code space if not using the peer rank API. + +#ifndef PM_PEER_RANKS_ENABLED +#define PM_PEER_RANKS_ENABLED 1 +#endif + +// PM_LESC_ENABLED - Enable/disable LESC support in Peer Manager. + + +// If set to true, you need to call nrf_ble_lesc_request_handler() in the main loop to respond to LESC-related BLE events. If LESC support is not required, set this to false to save code space. + +#ifndef PM_LESC_ENABLED +#define PM_LESC_ENABLED 1 +#endif + +// PM_RA_PROTECTION_ENABLED - Enable/disable protection against repeated pairing attempts in Peer Manager. +//========================================================== +#ifndef PM_RA_PROTECTION_ENABLED +#define PM_RA_PROTECTION_ENABLED 0 +#endif +// PM_RA_PROTECTION_TRACKED_PEERS_NUM - Maximum number of peers whose authorization status can be tracked. +#ifndef PM_RA_PROTECTION_TRACKED_PEERS_NUM +#define PM_RA_PROTECTION_TRACKED_PEERS_NUM 8 +#endif + +// PM_RA_PROTECTION_MIN_WAIT_INTERVAL - Minimum waiting interval (in ms) before a new pairing attempt can be initiated. +#ifndef PM_RA_PROTECTION_MIN_WAIT_INTERVAL +#define PM_RA_PROTECTION_MIN_WAIT_INTERVAL 4000 +#endif + +// PM_RA_PROTECTION_MAX_WAIT_INTERVAL - Maximum waiting interval (in ms) before a new pairing attempt can be initiated. +#ifndef PM_RA_PROTECTION_MAX_WAIT_INTERVAL +#define PM_RA_PROTECTION_MAX_WAIT_INTERVAL 64000 +#endif + +// PM_RA_PROTECTION_REWARD_PERIOD - Reward period (in ms). +// The waiting interval is gradually decreased when no new failed pairing attempts are made during reward period. + +#ifndef PM_RA_PROTECTION_REWARD_PERIOD +#define PM_RA_PROTECTION_REWARD_PERIOD 10000 +#endif + +// + +// PM_HANDLER_SEC_DELAY_MS - Delay before starting security. +// This might be necessary for interoperability reasons, especially as peripheral. + +#ifndef PM_HANDLER_SEC_DELAY_MS +#define PM_HANDLER_SEC_DELAY_MS 0 +#endif + +// + + +// nrf_ble_lesc - Le Secure Connection + +//========================================================== +// NRF_BLE_LESC_ENABLED - Enable LESC Module + + +#ifndef NRF_BLE_LESC_ENABLED +#define NRF_BLE_LESC_ENABLED 1 +#endif + +// NRF_BLE_LESC_GENERATE_NEW_KEYS - Generate new LESC keys after every pairing attempt. Keys are generated on the auth status event + + +#ifndef NRF_BLE_LESC_GENERATE_NEW_KEYS +#define NRF_BLE_LESC_GENERATE_NEW_KEYS 0 +#endif + +#ifndef NRF_CRYPTO_RNG_AUTO_INIT_ENABLED +#define NRF_CRYPTO_RNG_AUTO_INIT_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_BLE_Services + +//========================================================== +// BLE_ANCS_C_ENABLED - ble_ancs_c - Apple Notification Service Client + + +#ifndef BLE_ANCS_C_ENABLED +#define BLE_ANCS_C_ENABLED 0 +#endif + +// BLE_ANS_C_ENABLED - ble_ans_c - Alert Notification Service Client + + +#ifndef BLE_ANS_C_ENABLED +#define BLE_ANS_C_ENABLED 0 +#endif + +// BLE_BAS_C_ENABLED - ble_bas_c - Battery Service Client + + +#ifndef BLE_BAS_C_ENABLED +#define BLE_BAS_C_ENABLED 0 +#endif + +// BLE_BAS_ENABLED - ble_bas - Battery Service +//========================================================== +#ifndef BLE_BAS_ENABLED +#define BLE_BAS_ENABLED 0 +#endif +// BLE_BAS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef BLE_BAS_CONFIG_LOG_ENABLED +#define BLE_BAS_CONFIG_LOG_ENABLED 0 +#endif +// BLE_BAS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef BLE_BAS_CONFIG_LOG_LEVEL +#define BLE_BAS_CONFIG_LOG_LEVEL 3 +#endif + +// BLE_BAS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_BAS_CONFIG_INFO_COLOR +#define BLE_BAS_CONFIG_INFO_COLOR 0 +#endif + +// BLE_BAS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_BAS_CONFIG_DEBUG_COLOR +#define BLE_BAS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// BLE_CSCS_ENABLED - ble_cscs - Cycling Speed and Cadence Service + + +#ifndef BLE_CSCS_ENABLED +#define BLE_CSCS_ENABLED 0 +#endif + +// BLE_CTS_C_ENABLED - ble_cts_c - Current Time Service Client + + +#ifndef BLE_CTS_C_ENABLED +#define BLE_CTS_C_ENABLED 0 +#endif + +// BLE_DIS_ENABLED - ble_dis - Device Information Service + + +#ifndef BLE_DIS_ENABLED +#define BLE_DIS_ENABLED 1 +#endif + +// BLE_GLS_ENABLED - ble_gls - Glucose Service + + +#ifndef BLE_GLS_ENABLED +#define BLE_GLS_ENABLED 0 +#endif + +// BLE_HIDS_ENABLED - ble_hids - Human Interface Device Service + + +#ifndef BLE_HIDS_ENABLED +#define BLE_HIDS_ENABLED 0 +#endif + +// BLE_HRS_C_ENABLED - ble_hrs_c - Heart Rate Service Client + + +#ifndef BLE_HRS_C_ENABLED +#define BLE_HRS_C_ENABLED 0 +#endif + +// BLE_HRS_ENABLED - ble_hrs - Heart Rate Service + + +#ifndef BLE_HRS_ENABLED +#define BLE_HRS_ENABLED 0 +#endif + +// BLE_HTS_ENABLED - ble_hts - Health Thermometer Service + + +#ifndef BLE_HTS_ENABLED +#define BLE_HTS_ENABLED 0 +#endif + +// BLE_IAS_C_ENABLED - ble_ias_c - Immediate Alert Service Client + + +#ifndef BLE_IAS_C_ENABLED +#define BLE_IAS_C_ENABLED 0 +#endif + +// BLE_IAS_ENABLED - ble_ias - Immediate Alert Service +//========================================================== +#ifndef BLE_IAS_ENABLED +#define BLE_IAS_ENABLED 0 +#endif +// BLE_IAS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef BLE_IAS_CONFIG_LOG_ENABLED +#define BLE_IAS_CONFIG_LOG_ENABLED 0 +#endif +// BLE_IAS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef BLE_IAS_CONFIG_LOG_LEVEL +#define BLE_IAS_CONFIG_LOG_LEVEL 3 +#endif + +// BLE_IAS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_IAS_CONFIG_INFO_COLOR +#define BLE_IAS_CONFIG_INFO_COLOR 0 +#endif + +// BLE_IAS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_IAS_CONFIG_DEBUG_COLOR +#define BLE_IAS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// BLE_LBS_C_ENABLED - ble_lbs_c - Nordic LED Button Service Client + + +#ifndef BLE_LBS_C_ENABLED +#define BLE_LBS_C_ENABLED 0 +#endif + +// BLE_LBS_ENABLED - ble_lbs - LED Button Service + + +#ifndef BLE_LBS_ENABLED +#define BLE_LBS_ENABLED 0 +#endif + +// BLE_LLS_ENABLED - ble_lls - Link Loss Service + + +#ifndef BLE_LLS_ENABLED +#define BLE_LLS_ENABLED 0 +#endif + +// BLE_NUS_C_ENABLED - ble_nus_c - Nordic UART Central Service + + +#ifndef BLE_NUS_C_ENABLED +#define BLE_NUS_C_ENABLED 0 +#endif + +// BLE_NUS_ENABLED - ble_nus - Nordic UART Service +//========================================================== +#ifndef BLE_NUS_ENABLED +#define BLE_NUS_ENABLED 1 +#endif +// BLE_NUS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef BLE_NUS_CONFIG_LOG_ENABLED +#define BLE_NUS_CONFIG_LOG_ENABLED 0 +#endif +// BLE_NUS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef BLE_NUS_CONFIG_LOG_LEVEL +#define BLE_NUS_CONFIG_LOG_LEVEL 3 +#endif + +// BLE_NUS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_NUS_CONFIG_INFO_COLOR +#define BLE_NUS_CONFIG_INFO_COLOR 0 +#endif + +// BLE_NUS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef BLE_NUS_CONFIG_DEBUG_COLOR +#define BLE_NUS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// BLE_RSCS_C_ENABLED - ble_rscs_c - Running Speed and Cadence Client + + +#ifndef BLE_RSCS_C_ENABLED +#define BLE_RSCS_C_ENABLED 0 +#endif + +// BLE_RSCS_ENABLED - ble_rscs - Running Speed and Cadence Service + + +#ifndef BLE_RSCS_ENABLED +#define BLE_RSCS_ENABLED 0 +#endif + +// BLE_TPS_ENABLED - ble_tps - TX Power Service + + +#ifndef BLE_TPS_ENABLED +#define BLE_TPS_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Core + +//========================================================== +// NRF_MPU_LIB_ENABLED - nrf_mpu_lib - Module for MPU +//========================================================== +#ifndef NRF_MPU_LIB_ENABLED +#define NRF_MPU_LIB_ENABLED 0 +#endif +// NRF_MPU_LIB_CLI_CMDS - Enable CLI commands specific to the module. + + +#ifndef NRF_MPU_LIB_CLI_CMDS +#define NRF_MPU_LIB_CLI_CMDS 0 +#endif + +// + +// NRF_STACK_GUARD_ENABLED - nrf_stack_guard - Stack guard +//========================================================== +#ifndef NRF_STACK_GUARD_ENABLED +#define NRF_STACK_GUARD_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_SIZE - Size of the stack guard. + +// <5=> 32 bytes +// <6=> 64 bytes +// <7=> 128 bytes +// <8=> 256 bytes +// <9=> 512 bytes +// <10=> 1024 bytes +// <11=> 2048 bytes +// <12=> 4096 bytes + +#ifndef NRF_STACK_GUARD_CONFIG_SIZE +#define NRF_STACK_GUARD_CONFIG_SIZE 7 +#endif + +// + +// +//========================================================== + +// nRF_Crypto + +//========================================================== +// NRF_CRYPTO_ENABLED - nrf_crypto - Cryptography library. +//========================================================== +#ifndef NRF_CRYPTO_ENABLED +#define NRF_CRYPTO_ENABLED 1 +#endif +// NRF_CRYPTO_ALLOCATOR - Memory allocator + + +// Choose memory allocator used by nrf_crypto. Default is alloca if possible or nrf_malloc otherwise. If 'User macros' are selected, the user has to create 'nrf_crypto_allocator.h' file that contains NRF_CRYPTO_ALLOC, NRF_CRYPTO_FREE, and NRF_CRYPTO_ALLOC_ON_STACK. +// <0=> Default +// <1=> User macros +// <2=> On stack (alloca) +// <3=> C dynamic memory (malloc) +// <4=> SDK Memory Manager (nrf_malloc) + +#ifndef NRF_CRYPTO_ALLOCATOR +#define NRF_CRYPTO_ALLOCATOR 0 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_ENABLED - Enable the ARM Cryptocell CC310 reduced backend. + +// The CC310 hardware-accelerated cryptography backend with reduced functionality and footprint (only available on nRF52840). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED - Enable the secp224r1 elliptic curve support using CC310_BL. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP224R1_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED - Enable the secp256r1 elliptic curve support using CC310_BL. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED - CC310_BL SHA-256 hash functionality. + + +// CC310_BL backend implementation for hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED - nrf_cc310_bl buffers to RAM before running hash operation + + +// Enabling this makes hashing of addresses in FLASH range possible. Size of buffer allocated for hashing is set by NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE - nrf_cc310_bl hash outputs digests in little endian +// Makes the nrf_cc310_bl hash functions output digests in little endian format. Only for use in nRF SDK DFU! + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE +#define NRF_CRYPTO_BACKEND_CC310_BL_HASH_AUTOMATIC_RAM_BUFFER_SIZE 4096 +#endif + +// NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED - Enable Interrupts while support using CC310 bl. + + +// Select a library version compatible with the configuration. When interrupts are disable, a version named _noint must be used + +#ifndef NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_BL_INTERRUPTS_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_CC310_ENABLED - Enable the ARM Cryptocell CC310 backend. + +// The CC310 hardware-accelerated cryptography backend (only available on nRF52840). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CC310_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED - Enable the AES CBC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CBC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED - Enable the AES CTR mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CTR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED - Enable the AES ECB mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_ECB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED - Enable the AES CBC_MAC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CBC_MAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED - Enable the AES CMAC mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CMAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED - Enable the AES CCM mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED - Enable the AES CCM* mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_AES_CCM_STAR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED - Enable the CHACHA-POLY mode using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_CHACHA_POLY_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED - Enable the secp160r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED - Enable the secp160r2 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160R2_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED - Enable the secp192r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED - Enable the secp224r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED - Enable the secp256r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED - Enable the secp384r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED - Enable the secp521r1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP521R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED - Enable the secp160k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP160K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED - Enable the secp192k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP192K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED - Enable the secp224k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP224K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED - Enable the secp256k1 elliptic curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_SECP256K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED - Enable the Curve25519 curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_CURVE25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED - Enable the Ed25519 curve support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_ECC_ED25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED - CC310 SHA-256 hash functionality. + + +// CC310 backend implementation for hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED - CC310 SHA-512 hash functionality + + +// CC310 backend implementation for SHA-512 (in software). + +#ifndef NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HASH_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED - CC310 HMAC using SHA-256 + + +// CC310 backend implementation for HMAC using hardware-accelerated SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HMAC_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED - CC310 HMAC using SHA-512 + + +// CC310 backend implementation for HMAC using SHA-512 (in software). + +#ifndef NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_HMAC_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED - Enable RNG support using CC310. + + +#ifndef NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_RNG_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED - Enable Interrupts while support using CC310. + + +// Select a library version compatible with the configuration. When interrupts are disable, a version named _noint must be used + +#ifndef NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED +#define NRF_CRYPTO_BACKEND_CC310_INTERRUPTS_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_CIFRA_ENABLED - Enable the Cifra backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_CIFRA_ENABLED +#define NRF_CRYPTO_BACKEND_CIFRA_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED - Enable the AES EAX mode using Cifra. + + +#ifndef NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED +#define NRF_CRYPTO_BACKEND_CIFRA_AES_EAX_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED - Enable the mbed TLS backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED - Enable the AES CBC mode mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED - Enable the AES CTR mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CTR_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED - Enable the AES CFB mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CFB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED - Enable the AES ECB mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_ECB_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED - Enable the AES CBC MAC mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CBC_MAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED - Enable the AES CMAC mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CMAC_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED - Enable the AES CCM mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_CCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED - Enable the AES GCM mode using mbed TLS. + + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_AES_GCM_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve + + +// Enable this setting if you need secp192r1 (NIST 192-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED - Enable secp224r1 (NIST 224-bit) curve + + +// Enable this setting if you need secp224r1 (NIST 224-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED - Enable secp256r1 (NIST 256-bit) curve + + +// Enable this setting if you need secp256r1 (NIST 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED - Enable secp384r1 (NIST 384-bit) curve + + +// Enable this setting if you need secp384r1 (NIST 384-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED - Enable secp521r1 (NIST 521-bit) curve + + +// Enable this setting if you need secp521r1 (NIST 521-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP521R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED - Enable secp192k1 (Koblitz 192-bit) curve + + +// Enable this setting if you need secp192k1 (Koblitz 192-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP192K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED - Enable secp224k1 (Koblitz 224-bit) curve + + +// Enable this setting if you need secp224k1 (Koblitz 224-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP224K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED - Enable secp256k1 (Koblitz 256-bit) curve + + +// Enable this setting if you need secp256k1 (Koblitz 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_SECP256K1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED - Enable bp256r1 (Brainpool 256-bit) curve + + +// Enable this setting if you need bp256r1 (Brainpool 256-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED - Enable bp384r1 (Brainpool 384-bit) curve + + +// Enable this setting if you need bp384r1 (Brainpool 384-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP384R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED - Enable bp512r1 (Brainpool 512-bit) curve + + +// Enable this setting if you need bp512r1 (Brainpool 512-bit) support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_BP512R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED - Enable Curve25519 curve + + +// Enable this setting if you need Curve25519 support using MBEDTLS + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_ECC_CURVE25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED - Enable mbed TLS SHA-256 hash functionality. + + +// mbed TLS backend implementation for SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED - Enable mbed TLS SHA-512 hash functionality. + + +// mbed TLS backend implementation for SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HASH_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED - Enable mbed TLS HMAC using SHA-256. + + +// mbed TLS backend implementation for HMAC using SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED - Enable mbed TLS HMAC using SHA-512. + + +// mbed TLS backend implementation for HMAC using SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_MBEDTLS_HMAC_SHA512_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED - Enable the micro-ecc backend. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED 1 +#endif +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED - Enable secp192r1 (NIST 192-bit) curve + + +// Enable this setting if you need secp192r1 (NIST 192-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP192R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED - Enable secp224r1 (NIST 224-bit) curve + + +// Enable this setting if you need secp224r1 (NIST 224-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP224R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED - Enable secp256r1 (NIST 256-bit) curve + + +// Enable this setting if you need secp256r1 (NIST 256-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED - Enable secp256k1 (Koblitz 256-bit) curve + + +// Enable this setting if you need secp256k1 (Koblitz 256-bit) support using micro-ecc + +#ifndef NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED +#define NRF_CRYPTO_BACKEND_MICRO_ECC_ECC_SECP256K1_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED - Enable the nRF HW RNG backend. + +// The nRF HW backend provide access to RNG peripheral in nRF5x devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED 1 +#endif +// NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED - Enable mbed TLS CTR-DRBG algorithm. + +// Always recommended when using the nRF HW RNG as the context and temporary buffers are small. Consider disabling if using the CC310 RNG in a RAM constrained application. In this case, memory must be provided to nrf_crypto_rng_init, or it can be allocated internally provided that NRF_CRYPTO_ALLOCATOR does not allocate memory on the stack. + +#ifndef NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED +#define NRF_CRYPTO_RNG_STATIC_MEMORY_BUFFERS_ENABLED 1 +#endif + + +// Enable mbed TLS CTR-DRBG standardized by NIST (NIST SP 800-90A Rev. 1). The nRF HW RNG is used as an entropy source for seeding. + +#ifndef NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_HW_RNG_MBEDTLS_CTR_DRBG_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_NRF_SW_ENABLED - Enable the legacy nRFx sw for crypto. + +// The nRF SW cryptography backend (only used in bootloader context). +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_NRF_SW_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_SW_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED - nRF SW hash backend support for SHA-256 + + +// The nRF SW backend provide access to nRF SDK legacy hash implementation of SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_NRF_SW_HASH_SHA256_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_OBERON_ENABLED - Enable the Oberon backend + +// The Oberon backend +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_OBERON_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED - Enable the CHACHA-POLY mode using Oberon. + + +#ifndef NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_CHACHA_POLY_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED - Enable secp256r1 curve + + +// Enable this setting if you need secp256r1 curve support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_SECP256R1_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED - Enable Curve25519 ECDH + + +// Enable this setting if you need Curve25519 ECDH support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_CURVE25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED - Enable Ed25519 signature scheme + + +// Enable this setting if you need Ed25519 support using Oberon library + +#ifndef NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_ECC_ED25519_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED - Oberon SHA-256 hash functionality + + +// Oberon backend implementation for SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HASH_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED - Oberon SHA-512 hash functionality + + +// Oberon backend implementation for SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HASH_SHA512_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED - Oberon HMAC using SHA-256 + + +// Oberon backend implementation for HMAC using SHA-256. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA256_ENABLED 1 +#endif + +// NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED - Oberon HMAC using SHA-512 + + +// Oberon backend implementation for HMAC using SHA-512. + +#ifndef NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED +#define NRF_CRYPTO_BACKEND_OBERON_HMAC_SHA512_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_BACKEND_OPTIGA_ENABLED - Enable the nrf_crypto Optiga Trust X backend. + +// Enables the nrf_crypto backend for Optiga Trust X devices. +//========================================================== +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_ENABLED 0 +#endif +// NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED - Optiga backend support for RNG + + +// The Optiga backend provide external chip RNG. + +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_RNG_ENABLED 0 +#endif + +// NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED - Optiga backend support for ECC secp256r1 + + +// The Optiga backend provide external chip ECC using secp256r1. + +#ifndef NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED +#define NRF_CRYPTO_BACKEND_OPTIGA_ECC_SECP256R1_ENABLED 1 +#endif + +// + +// NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED - Big-endian byte order in raw Curve25519 data + + +// Enable big-endian byte order in Curve25519 API, if set to 1. Use little-endian, if set to 0. + +#ifndef NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED +#define NRF_CRYPTO_CURVE25519_BIG_ENDIAN_ENABLED 0 +#endif + +// + +// +//========================================================== + +// nRF_DFU + +//========================================================== +// ble_dfu - Device Firmware Update + +//========================================================== +// BLE_DFU_ENABLED - Enable DFU Service. + + +#ifndef BLE_DFU_ENABLED +#define BLE_DFU_ENABLED 0 +#endif + +// NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS - Buttonless DFU supports bonds. + + +#ifndef NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS +#define NRF_DFU_BLE_BUTTONLESS_SUPPORTS_BONDS 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Drivers + +//========================================================== +// COMP_ENABLED - nrf_drv_comp - COMP peripheral driver - legacy layer +//========================================================== +#ifndef COMP_ENABLED +#define COMP_ENABLED 0 +#endif +// COMP_CONFIG_REF - Reference voltage + +// <0=> Internal 1.2V +// <1=> Internal 1.8V +// <2=> Internal 2.4V +// <4=> VDD +// <7=> ARef + +#ifndef COMP_CONFIG_REF +#define COMP_CONFIG_REF 1 +#endif + +// COMP_CONFIG_MAIN_MODE - Main mode + +// <0=> Single ended +// <1=> Differential + +#ifndef COMP_CONFIG_MAIN_MODE +#define COMP_CONFIG_MAIN_MODE 0 +#endif + +// COMP_CONFIG_SPEED_MODE - Speed mode + +// <0=> Low power +// <1=> Normal +// <2=> High speed + +#ifndef COMP_CONFIG_SPEED_MODE +#define COMP_CONFIG_SPEED_MODE 2 +#endif + +// COMP_CONFIG_HYST - Hystheresis + +// <0=> No +// <1=> 50mV + +#ifndef COMP_CONFIG_HYST +#define COMP_CONFIG_HYST 0 +#endif + +// COMP_CONFIG_ISOURCE - Current Source + +// <0=> Off +// <1=> 2.5 uA +// <2=> 5 uA +// <3=> 10 uA + +#ifndef COMP_CONFIG_ISOURCE +#define COMP_CONFIG_ISOURCE 0 +#endif + +// COMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_INPUT +#define COMP_CONFIG_INPUT 0 +#endif + +// COMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef COMP_CONFIG_IRQ_PRIORITY +#define COMP_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// EGU_ENABLED - nrf_drv_swi - SWI(EGU) peripheral driver - legacy layer + + +#ifndef EGU_ENABLED +#define EGU_ENABLED 0 +#endif + +// GPIOTE_ENABLED - nrf_drv_gpiote - GPIOTE peripheral driver - legacy layer +//========================================================== +#ifndef GPIOTE_ENABLED +#define GPIOTE_ENABLED 1 +#endif +// GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins +#ifndef GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +// GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef GPIOTE_CONFIG_IRQ_PRIORITY +#define GPIOTE_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// I2S_ENABLED - nrf_drv_i2s - I2S peripheral driver - legacy layer +//========================================================== +#ifndef I2S_ENABLED +#define I2S_ENABLED 0 +#endif +// I2S_CONFIG_SCK_PIN - SCK pin <0-31> + + +#ifndef I2S_CONFIG_SCK_PIN +#define I2S_CONFIG_SCK_PIN 31 +#endif + +// I2S_CONFIG_LRCK_PIN - LRCK pin <1-31> + + +#ifndef I2S_CONFIG_LRCK_PIN +#define I2S_CONFIG_LRCK_PIN 30 +#endif + +// I2S_CONFIG_MCK_PIN - MCK pin +#ifndef I2S_CONFIG_MCK_PIN +#define I2S_CONFIG_MCK_PIN 255 +#endif + +// I2S_CONFIG_SDOUT_PIN - SDOUT pin <0-31> + + +#ifndef I2S_CONFIG_SDOUT_PIN +#define I2S_CONFIG_SDOUT_PIN 29 +#endif + +// I2S_CONFIG_SDIN_PIN - SDIN pin <0-31> + + +#ifndef I2S_CONFIG_SDIN_PIN +#define I2S_CONFIG_SDIN_PIN 28 +#endif + +// I2S_CONFIG_MASTER - Mode + +// <0=> Master +// <1=> Slave + +#ifndef I2S_CONFIG_MASTER +#define I2S_CONFIG_MASTER 0 +#endif + +// I2S_CONFIG_FORMAT - Format + +// <0=> I2S +// <1=> Aligned + +#ifndef I2S_CONFIG_FORMAT +#define I2S_CONFIG_FORMAT 0 +#endif + +// I2S_CONFIG_ALIGN - Alignment + +// <0=> Left +// <1=> Right + +#ifndef I2S_CONFIG_ALIGN +#define I2S_CONFIG_ALIGN 0 +#endif + +// I2S_CONFIG_SWIDTH - Sample width (bits) + +// <0=> 8 +// <1=> 16 +// <2=> 24 + +#ifndef I2S_CONFIG_SWIDTH +#define I2S_CONFIG_SWIDTH 1 +#endif + +// I2S_CONFIG_CHANNELS - Channels + +// <0=> Stereo +// <1=> Left +// <2=> Right + +#ifndef I2S_CONFIG_CHANNELS +#define I2S_CONFIG_CHANNELS 1 +#endif + +// I2S_CONFIG_MCK_SETUP - MCK behavior + +// <0=> Disabled +// <2147483648=> 32MHz/2 +// <1342177280=> 32MHz/3 +// <1073741824=> 32MHz/4 +// <805306368=> 32MHz/5 +// <671088640=> 32MHz/6 +// <536870912=> 32MHz/8 +// <402653184=> 32MHz/10 +// <369098752=> 32MHz/11 +// <285212672=> 32MHz/15 +// <268435456=> 32MHz/16 +// <201326592=> 32MHz/21 +// <184549376=> 32MHz/23 +// <142606336=> 32MHz/30 +// <138412032=> 32MHz/31 +// <134217728=> 32MHz/32 +// <100663296=> 32MHz/42 +// <68157440=> 32MHz/63 +// <34340864=> 32MHz/125 + +#ifndef I2S_CONFIG_MCK_SETUP +#define I2S_CONFIG_MCK_SETUP 536870912 +#endif + +// I2S_CONFIG_RATIO - MCK/LRCK ratio + +// <0=> 32x +// <1=> 48x +// <2=> 64x +// <3=> 96x +// <4=> 128x +// <5=> 192x +// <6=> 256x +// <7=> 384x +// <8=> 512x + +#ifndef I2S_CONFIG_RATIO +#define I2S_CONFIG_RATIO 2000 +#endif + +// I2S_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef I2S_CONFIG_IRQ_PRIORITY +#define I2S_CONFIG_IRQ_PRIORITY 6 +#endif + +// I2S_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef I2S_CONFIG_LOG_ENABLED +#define I2S_CONFIG_LOG_ENABLED 0 +#endif +// I2S_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef I2S_CONFIG_LOG_LEVEL +#define I2S_CONFIG_LOG_LEVEL 3 +#endif + +// I2S_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_INFO_COLOR +#define I2S_CONFIG_INFO_COLOR 0 +#endif + +// I2S_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef I2S_CONFIG_DEBUG_COLOR +#define I2S_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// LPCOMP_ENABLED - nrf_drv_lpcomp - LPCOMP peripheral driver - legacy layer +//========================================================== +#ifndef LPCOMP_ENABLED +#define LPCOMP_ENABLED 0 +#endif +// LPCOMP_CONFIG_REFERENCE - Reference voltage + +// <0=> Supply 1/8 +// <1=> Supply 2/8 +// <2=> Supply 3/8 +// <3=> Supply 4/8 +// <4=> Supply 5/8 +// <5=> Supply 6/8 +// <6=> Supply 7/8 +// <8=> Supply 1/16 (nRF52) +// <9=> Supply 3/16 (nRF52) +// <10=> Supply 5/16 (nRF52) +// <11=> Supply 7/16 (nRF52) +// <12=> Supply 9/16 (nRF52) +// <13=> Supply 11/16 (nRF52) +// <14=> Supply 13/16 (nRF52) +// <15=> Supply 15/16 (nRF52) +// <7=> External Ref 0 +// <65543=> External Ref 1 + +#ifndef LPCOMP_CONFIG_REFERENCE +#define LPCOMP_CONFIG_REFERENCE 3 +#endif + +// LPCOMP_CONFIG_DETECTION - Detection + +// <0=> Crossing +// <1=> Up +// <2=> Down + +#ifndef LPCOMP_CONFIG_DETECTION +#define LPCOMP_CONFIG_DETECTION 2 +#endif + +// LPCOMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_INPUT +#define LPCOMP_CONFIG_INPUT 0 +#endif + +// LPCOMP_CONFIG_HYST - Hysteresis + + +#ifndef LPCOMP_CONFIG_HYST +#define LPCOMP_CONFIG_HYST 0 +#endif + +// LPCOMP_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef LPCOMP_CONFIG_IRQ_PRIORITY +#define LPCOMP_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// NRFX_CLOCK_ENABLED - nrfx_clock - CLOCK peripheral driver +//========================================================== +#ifndef NRFX_CLOCK_ENABLED +#define NRFX_CLOCK_ENABLED 1 +#endif +// NRFX_CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth +// <131073=> External Low Swing +// <196609=> External Full Swing + +#ifndef NRFX_CLOCK_CONFIG_LF_SRC +#define NRFX_CLOCK_CONFIG_LF_SRC 1 +#endif + +// NRFX_CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_CLOCK_CONFIG_IRQ_PRIORITY +#define NRFX_CLOCK_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_CLOCK_CONFIG_LOG_ENABLED +#define NRFX_CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_CLOCK_CONFIG_LOG_LEVEL +#define NRFX_CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_CLOCK_CONFIG_INFO_COLOR +#define NRFX_CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_CLOCK_CONFIG_DEBUG_COLOR +#define NRFX_CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_COMP_ENABLED - nrfx_comp - COMP peripheral driver +//========================================================== +#ifndef NRFX_COMP_ENABLED +#define NRFX_COMP_ENABLED 0 +#endif +// NRFX_COMP_CONFIG_REF - Reference voltage + +// <0=> Internal 1.2V +// <1=> Internal 1.8V +// <2=> Internal 2.4V +// <4=> VDD +// <7=> ARef + +#ifndef NRFX_COMP_CONFIG_REF +#define NRFX_COMP_CONFIG_REF 1 +#endif + +// NRFX_COMP_CONFIG_MAIN_MODE - Main mode + +// <0=> Single ended +// <1=> Differential + +#ifndef NRFX_COMP_CONFIG_MAIN_MODE +#define NRFX_COMP_CONFIG_MAIN_MODE 0 +#endif + +// NRFX_COMP_CONFIG_SPEED_MODE - Speed mode + +// <0=> Low power +// <1=> Normal +// <2=> High speed + +#ifndef NRFX_COMP_CONFIG_SPEED_MODE +#define NRFX_COMP_CONFIG_SPEED_MODE 2 +#endif + +// NRFX_COMP_CONFIG_HYST - Hystheresis + +// <0=> No +// <1=> 50mV + +#ifndef NRFX_COMP_CONFIG_HYST +#define NRFX_COMP_CONFIG_HYST 0 +#endif + +// NRFX_COMP_CONFIG_ISOURCE - Current Source + +// <0=> Off +// <1=> 2.5 uA +// <2=> 5 uA +// <3=> 10 uA + +#ifndef NRFX_COMP_CONFIG_ISOURCE +#define NRFX_COMP_CONFIG_ISOURCE 0 +#endif + +// NRFX_COMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_COMP_CONFIG_INPUT +#define NRFX_COMP_CONFIG_INPUT 0 +#endif + +// NRFX_COMP_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_COMP_CONFIG_IRQ_PRIORITY +#define NRFX_COMP_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_COMP_CONFIG_LOG_ENABLED +#define NRFX_COMP_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_COMP_CONFIG_LOG_LEVEL +#define NRFX_COMP_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_COMP_CONFIG_INFO_COLOR +#define NRFX_COMP_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_COMP_CONFIG_DEBUG_COLOR +#define NRFX_COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_GPIOTE_ENABLED - nrfx_gpiote - GPIOTE peripheral driver +//========================================================== +#ifndef NRFX_GPIOTE_ENABLED +#define NRFX_GPIOTE_ENABLED 1 +#endif +// NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS - Number of lower power input pins +#ifndef NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS +#define NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 1 +#endif + +// NRFX_GPIOTE_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_GPIOTE_CONFIG_IRQ_PRIORITY +#define NRFX_GPIOTE_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_GPIOTE_CONFIG_LOG_ENABLED +#define NRFX_GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_GPIOTE_CONFIG_LOG_LEVEL +#define NRFX_GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_GPIOTE_CONFIG_INFO_COLOR +#define NRFX_GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_GPIOTE_CONFIG_DEBUG_COLOR +#define NRFX_GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_I2S_ENABLED - nrfx_i2s - I2S peripheral driver +//========================================================== +#ifndef NRFX_I2S_ENABLED +#define NRFX_I2S_ENABLED 0 +#endif +// NRFX_I2S_CONFIG_SCK_PIN - SCK pin <0-31> + + +#ifndef NRFX_I2S_CONFIG_SCK_PIN +#define NRFX_I2S_CONFIG_SCK_PIN 31 +#endif + +// NRFX_I2S_CONFIG_LRCK_PIN - LRCK pin <1-31> + + +#ifndef NRFX_I2S_CONFIG_LRCK_PIN +#define NRFX_I2S_CONFIG_LRCK_PIN 30 +#endif + +// NRFX_I2S_CONFIG_MCK_PIN - MCK pin +#ifndef NRFX_I2S_CONFIG_MCK_PIN +#define NRFX_I2S_CONFIG_MCK_PIN 255 +#endif + +// NRFX_I2S_CONFIG_SDOUT_PIN - SDOUT pin <0-31> + + +#ifndef NRFX_I2S_CONFIG_SDOUT_PIN +#define NRFX_I2S_CONFIG_SDOUT_PIN 29 +#endif + +// NRFX_I2S_CONFIG_SDIN_PIN - SDIN pin <0-31> + + +#ifndef NRFX_I2S_CONFIG_SDIN_PIN +#define NRFX_I2S_CONFIG_SDIN_PIN 28 +#endif + +// NRFX_I2S_CONFIG_MASTER - Mode + +// <0=> Master +// <1=> Slave + +#ifndef NRFX_I2S_CONFIG_MASTER +#define NRFX_I2S_CONFIG_MASTER 0 +#endif + +// NRFX_I2S_CONFIG_FORMAT - Format + +// <0=> I2S +// <1=> Aligned + +#ifndef NRFX_I2S_CONFIG_FORMAT +#define NRFX_I2S_CONFIG_FORMAT 0 +#endif + +// NRFX_I2S_CONFIG_ALIGN - Alignment + +// <0=> Left +// <1=> Right + +#ifndef NRFX_I2S_CONFIG_ALIGN +#define NRFX_I2S_CONFIG_ALIGN 0 +#endif + +// NRFX_I2S_CONFIG_SWIDTH - Sample width (bits) + +// <0=> 8 +// <1=> 16 +// <2=> 24 + +#ifndef NRFX_I2S_CONFIG_SWIDTH +#define NRFX_I2S_CONFIG_SWIDTH 1 +#endif + +// NRFX_I2S_CONFIG_CHANNELS - Channels + +// <0=> Stereo +// <1=> Left +// <2=> Right + +#ifndef NRFX_I2S_CONFIG_CHANNELS +#define NRFX_I2S_CONFIG_CHANNELS 1 +#endif + +// NRFX_I2S_CONFIG_MCK_SETUP - MCK behavior + +// <0=> Disabled +// <2147483648=> 32MHz/2 +// <1342177280=> 32MHz/3 +// <1073741824=> 32MHz/4 +// <805306368=> 32MHz/5 +// <671088640=> 32MHz/6 +// <536870912=> 32MHz/8 +// <402653184=> 32MHz/10 +// <369098752=> 32MHz/11 +// <285212672=> 32MHz/15 +// <268435456=> 32MHz/16 +// <201326592=> 32MHz/21 +// <184549376=> 32MHz/23 +// <142606336=> 32MHz/30 +// <138412032=> 32MHz/31 +// <134217728=> 32MHz/32 +// <100663296=> 32MHz/42 +// <68157440=> 32MHz/63 +// <34340864=> 32MHz/125 + +#ifndef NRFX_I2S_CONFIG_MCK_SETUP +#define NRFX_I2S_CONFIG_MCK_SETUP 536870912 +#endif + +// NRFX_I2S_CONFIG_RATIO - MCK/LRCK ratio + +// <0=> 32x +// <1=> 48x +// <2=> 64x +// <3=> 96x +// <4=> 128x +// <5=> 192x +// <6=> 256x +// <7=> 384x +// <8=> 512x + +#ifndef NRFX_I2S_CONFIG_RATIO +#define NRFX_I2S_CONFIG_RATIO 2000 +#endif + +// NRFX_I2S_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_I2S_CONFIG_IRQ_PRIORITY +#define NRFX_I2S_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_I2S_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_I2S_CONFIG_LOG_ENABLED +#define NRFX_I2S_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_I2S_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_I2S_CONFIG_LOG_LEVEL +#define NRFX_I2S_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_I2S_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_I2S_CONFIG_INFO_COLOR +#define NRFX_I2S_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_I2S_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_I2S_CONFIG_DEBUG_COLOR +#define NRFX_I2S_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_LPCOMP_ENABLED - nrfx_lpcomp - LPCOMP peripheral driver +//========================================================== +#ifndef NRFX_LPCOMP_ENABLED +#define NRFX_LPCOMP_ENABLED 0 +#endif +// NRFX_LPCOMP_CONFIG_REFERENCE - Reference voltage + +// <0=> Supply 1/8 +// <1=> Supply 2/8 +// <2=> Supply 3/8 +// <3=> Supply 4/8 +// <4=> Supply 5/8 +// <5=> Supply 6/8 +// <6=> Supply 7/8 +// <8=> Supply 1/16 (nRF52) +// <9=> Supply 3/16 (nRF52) +// <10=> Supply 5/16 (nRF52) +// <11=> Supply 7/16 (nRF52) +// <12=> Supply 9/16 (nRF52) +// <13=> Supply 11/16 (nRF52) +// <14=> Supply 13/16 (nRF52) +// <15=> Supply 15/16 (nRF52) +// <7=> External Ref 0 +// <65543=> External Ref 1 + +#ifndef NRFX_LPCOMP_CONFIG_REFERENCE +#define NRFX_LPCOMP_CONFIG_REFERENCE 3 +#endif + +// NRFX_LPCOMP_CONFIG_DETECTION - Detection + +// <0=> Crossing +// <1=> Up +// <2=> Down + +#ifndef NRFX_LPCOMP_CONFIG_DETECTION +#define NRFX_LPCOMP_CONFIG_DETECTION 2 +#endif + +// NRFX_LPCOMP_CONFIG_INPUT - Analog input + +// <0=> 0 +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_LPCOMP_CONFIG_INPUT +#define NRFX_LPCOMP_CONFIG_INPUT 0 +#endif + +// NRFX_LPCOMP_CONFIG_HYST - Hysteresis + + +#ifndef NRFX_LPCOMP_CONFIG_HYST +#define NRFX_LPCOMP_CONFIG_HYST 0 +#endif + +// NRFX_LPCOMP_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_LPCOMP_CONFIG_IRQ_PRIORITY +#define NRFX_LPCOMP_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_LPCOMP_CONFIG_LOG_ENABLED +#define NRFX_LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_LPCOMP_CONFIG_LOG_LEVEL +#define NRFX_LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_LPCOMP_CONFIG_INFO_COLOR +#define NRFX_LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_LPCOMP_CONFIG_DEBUG_COLOR +#define NRFX_LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_NFCT_ENABLED - nrfx_nfct - NFCT peripheral driver +//========================================================== +#ifndef NRFX_NFCT_ENABLED +#define NRFX_NFCT_ENABLED 0 +#endif +// NRFX_NFCT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_NFCT_CONFIG_IRQ_PRIORITY +#define NRFX_NFCT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_NFCT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_NFCT_CONFIG_LOG_ENABLED +#define NRFX_NFCT_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_NFCT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_NFCT_CONFIG_LOG_LEVEL +#define NRFX_NFCT_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_NFCT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_NFCT_CONFIG_INFO_COLOR +#define NRFX_NFCT_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_NFCT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_NFCT_CONFIG_DEBUG_COLOR +#define NRFX_NFCT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_PDM_ENABLED - nrfx_pdm - PDM peripheral driver +//========================================================== +#ifndef NRFX_PDM_ENABLED +#define NRFX_PDM_ENABLED 0 +#endif +// NRFX_PDM_CONFIG_MODE - Mode + +// <0=> Stereo +// <1=> Mono + +#ifndef NRFX_PDM_CONFIG_MODE +#define NRFX_PDM_CONFIG_MODE 1 +#endif + +// NRFX_PDM_CONFIG_EDGE - Edge + +// <0=> Left falling +// <1=> Left rising + +#ifndef NRFX_PDM_CONFIG_EDGE +#define NRFX_PDM_CONFIG_EDGE 0 +#endif + +// NRFX_PDM_CONFIG_CLOCK_FREQ - Clock frequency + +// <134217728=> 1000k +// <138412032=> 1032k (default) +// <142606336=> 1067k + +#ifndef NRFX_PDM_CONFIG_CLOCK_FREQ +#define NRFX_PDM_CONFIG_CLOCK_FREQ 138412032 +#endif + +// NRFX_PDM_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_PDM_CONFIG_IRQ_PRIORITY +#define NRFX_PDM_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PDM_CONFIG_LOG_ENABLED +#define NRFX_PDM_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PDM_CONFIG_LOG_LEVEL +#define NRFX_PDM_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PDM_CONFIG_INFO_COLOR +#define NRFX_PDM_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PDM_CONFIG_DEBUG_COLOR +#define NRFX_PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_POWER_ENABLED - nrfx_power - POWER peripheral driver +//========================================================== +#ifndef NRFX_POWER_ENABLED +#define NRFX_POWER_ENABLED 0 +#endif +// NRFX_POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_POWER_CONFIG_IRQ_PRIORITY +#define NRFX_POWER_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef NRFX_POWER_CONFIG_DEFAULT_DCDCEN +#define NRFX_POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// NRFX_POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef NRFX_POWER_CONFIG_DEFAULT_DCDCENHV +#define NRFX_POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + +// NRFX_PPI_ENABLED - nrfx_ppi - PPI peripheral allocator +//========================================================== +#ifndef NRFX_PPI_ENABLED +#define NRFX_PPI_ENABLED 0 +#endif +// NRFX_PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PPI_CONFIG_LOG_ENABLED +#define NRFX_PPI_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PPI_CONFIG_LOG_LEVEL +#define NRFX_PPI_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PPI_CONFIG_INFO_COLOR +#define NRFX_PPI_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PPI_CONFIG_DEBUG_COLOR +#define NRFX_PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_PRS_ENABLED - nrfx_prs - Peripheral Resource Sharing module +//========================================================== +#ifndef NRFX_PRS_ENABLED +#define NRFX_PRS_ENABLED 1 +#endif +// NRFX_PRS_BOX_0_ENABLED - Enables box 0 in the module. + + +#ifndef NRFX_PRS_BOX_0_ENABLED +#define NRFX_PRS_BOX_0_ENABLED 0 +#endif + +// NRFX_PRS_BOX_1_ENABLED - Enables box 1 in the module. + + +#ifndef NRFX_PRS_BOX_1_ENABLED +#define NRFX_PRS_BOX_1_ENABLED 0 +#endif + +// NRFX_PRS_BOX_2_ENABLED - Enables box 2 in the module. + + +#ifndef NRFX_PRS_BOX_2_ENABLED +#define NRFX_PRS_BOX_2_ENABLED 0 +#endif + +// NRFX_PRS_BOX_3_ENABLED - Enables box 3 in the module. + + +#ifndef NRFX_PRS_BOX_3_ENABLED +#define NRFX_PRS_BOX_3_ENABLED 0 +#endif + +// NRFX_PRS_BOX_4_ENABLED - Enables box 4 in the module. + + +#ifndef NRFX_PRS_BOX_4_ENABLED +#define NRFX_PRS_BOX_4_ENABLED 1 +#endif + +// NRFX_PRS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PRS_CONFIG_LOG_ENABLED +#define NRFX_PRS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PRS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PRS_CONFIG_LOG_LEVEL +#define NRFX_PRS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PRS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_INFO_COLOR +#define NRFX_PRS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PRS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PRS_CONFIG_DEBUG_COLOR +#define NRFX_PRS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_PWM_ENABLED - nrfx_pwm - PWM peripheral driver +//========================================================== +#ifndef NRFX_PWM_ENABLED +#define NRFX_PWM_ENABLED 0 +#endif +// NRFX_PWM0_ENABLED - Enable PWM0 instance + + +#ifndef NRFX_PWM0_ENABLED +#define NRFX_PWM0_ENABLED 0 +#endif + +// NRFX_PWM1_ENABLED - Enable PWM1 instance + + +#ifndef NRFX_PWM1_ENABLED +#define NRFX_PWM1_ENABLED 0 +#endif + +// NRFX_PWM2_ENABLED - Enable PWM2 instance + + +#ifndef NRFX_PWM2_ENABLED +#define NRFX_PWM2_ENABLED 0 +#endif + +// NRFX_PWM3_ENABLED - Enable PWM3 instance + + +#ifndef NRFX_PWM3_ENABLED +#define NRFX_PWM3_ENABLED 0 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> + + +#ifndef NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT0_PIN 31 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN - Out1 pin <0-31> + + +#ifndef NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT1_PIN 31 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN - Out2 pin <0-31> + + +#ifndef NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT2_PIN 31 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN - Out3 pin <0-31> + + +#ifndef NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN +#define NRFX_PWM_DEFAULT_CONFIG_OUT3_PIN 31 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK - Base clock + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz + +#ifndef NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK +#define NRFX_PWM_DEFAULT_CONFIG_BASE_CLOCK 4 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE - Count mode + +// <0=> Up +// <1=> Up and Down + +#ifndef NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE +#define NRFX_PWM_DEFAULT_CONFIG_COUNT_MODE 0 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE - Top value +#ifndef NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE +#define NRFX_PWM_DEFAULT_CONFIG_TOP_VALUE 1000 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE - Load mode + +// <0=> Common +// <1=> Grouped +// <2=> Individual +// <3=> Waveform + +#ifndef NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE +#define NRFX_PWM_DEFAULT_CONFIG_LOAD_MODE 0 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_STEP_MODE - Step mode + +// <0=> Auto +// <1=> Triggered + +#ifndef NRFX_PWM_DEFAULT_CONFIG_STEP_MODE +#define NRFX_PWM_DEFAULT_CONFIG_STEP_MODE 0 +#endif + +// NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_PWM_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_PWM_CONFIG_LOG_ENABLED +#define NRFX_PWM_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_PWM_CONFIG_LOG_LEVEL +#define NRFX_PWM_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PWM_CONFIG_INFO_COLOR +#define NRFX_PWM_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_PWM_CONFIG_DEBUG_COLOR +#define NRFX_PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_QDEC_ENABLED - nrfx_qdec - QDEC peripheral driver +//========================================================== +#ifndef NRFX_QDEC_ENABLED +#define NRFX_QDEC_ENABLED 0 +#endif +// NRFX_QDEC_CONFIG_REPORTPER - Report period + +// <0=> 10 Samples +// <1=> 40 Samples +// <2=> 80 Samples +// <3=> 120 Samples +// <4=> 160 Samples +// <5=> 200 Samples +// <6=> 240 Samples +// <7=> 280 Samples + +#ifndef NRFX_QDEC_CONFIG_REPORTPER +#define NRFX_QDEC_CONFIG_REPORTPER 0 +#endif + +// NRFX_QDEC_CONFIG_SAMPLEPER - Sample period + +// <0=> 128 us +// <1=> 256 us +// <2=> 512 us +// <3=> 1024 us +// <4=> 2048 us +// <5=> 4096 us +// <6=> 8192 us +// <7=> 16384 us + +#ifndef NRFX_QDEC_CONFIG_SAMPLEPER +#define NRFX_QDEC_CONFIG_SAMPLEPER 7 +#endif + +// NRFX_QDEC_CONFIG_PIO_A - A pin <0-31> + + +#ifndef NRFX_QDEC_CONFIG_PIO_A +#define NRFX_QDEC_CONFIG_PIO_A 31 +#endif + +// NRFX_QDEC_CONFIG_PIO_B - B pin <0-31> + + +#ifndef NRFX_QDEC_CONFIG_PIO_B +#define NRFX_QDEC_CONFIG_PIO_B 31 +#endif + +// NRFX_QDEC_CONFIG_PIO_LED - LED pin <0-31> + + +#ifndef NRFX_QDEC_CONFIG_PIO_LED +#define NRFX_QDEC_CONFIG_PIO_LED 31 +#endif + +// NRFX_QDEC_CONFIG_LEDPRE - LED pre +#ifndef NRFX_QDEC_CONFIG_LEDPRE +#define NRFX_QDEC_CONFIG_LEDPRE 511 +#endif + +// NRFX_QDEC_CONFIG_LEDPOL - LED polarity + +// <0=> Active low +// <1=> Active high + +#ifndef NRFX_QDEC_CONFIG_LEDPOL +#define NRFX_QDEC_CONFIG_LEDPOL 1 +#endif + +// NRFX_QDEC_CONFIG_DBFEN - Debouncing enable + + +#ifndef NRFX_QDEC_CONFIG_DBFEN +#define NRFX_QDEC_CONFIG_DBFEN 0 +#endif + +// NRFX_QDEC_CONFIG_SAMPLE_INTEN - Sample ready interrupt enable + + +#ifndef NRFX_QDEC_CONFIG_SAMPLE_INTEN +#define NRFX_QDEC_CONFIG_SAMPLE_INTEN 0 +#endif + +// NRFX_QDEC_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_QDEC_CONFIG_IRQ_PRIORITY +#define NRFX_QDEC_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_QDEC_CONFIG_LOG_ENABLED +#define NRFX_QDEC_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_QDEC_CONFIG_LOG_LEVEL +#define NRFX_QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_QDEC_CONFIG_INFO_COLOR +#define NRFX_QDEC_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_QDEC_CONFIG_DEBUG_COLOR +#define NRFX_QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_QSPI_ENABLED - nrfx_qspi - QSPI peripheral driver +//========================================================== +#ifndef NRFX_QSPI_ENABLED +#define NRFX_QSPI_ENABLED 0 +#endif +// NRFX_QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255> + + +#ifndef NRFX_QSPI_CONFIG_SCK_DELAY +#define NRFX_QSPI_CONFIG_SCK_DELAY 1 +#endif + +// NRFX_QSPI_CONFIG_XIP_OFFSET - Address offset in the external memory for Execute in Place operation. +#ifndef NRFX_QSPI_CONFIG_XIP_OFFSET +#define NRFX_QSPI_CONFIG_XIP_OFFSET 0 +#endif + +// NRFX_QSPI_CONFIG_READOC - Number of data lines and opcode used for reading. + +// <0=> FastRead +// <1=> Read2O +// <2=> Read2IO +// <3=> Read4O +// <4=> Read4IO + +#ifndef NRFX_QSPI_CONFIG_READOC +#define NRFX_QSPI_CONFIG_READOC 0 +#endif + +// NRFX_QSPI_CONFIG_WRITEOC - Number of data lines and opcode used for writing. + +// <0=> PP +// <1=> PP2O +// <2=> PP4O +// <3=> PP4IO + +#ifndef NRFX_QSPI_CONFIG_WRITEOC +#define NRFX_QSPI_CONFIG_WRITEOC 0 +#endif + +// NRFX_QSPI_CONFIG_ADDRMODE - Addressing mode. + +// <0=> 24bit +// <1=> 32bit + +#ifndef NRFX_QSPI_CONFIG_ADDRMODE +#define NRFX_QSPI_CONFIG_ADDRMODE 0 +#endif + +// NRFX_QSPI_CONFIG_MODE - SPI mode. + +// <0=> Mode 0 +// <1=> Mode 1 + +#ifndef NRFX_QSPI_CONFIG_MODE +#define NRFX_QSPI_CONFIG_MODE 0 +#endif + +// NRFX_QSPI_CONFIG_FREQUENCY - Frequency divider. + +// <0=> 32MHz/1 +// <1=> 32MHz/2 +// <2=> 32MHz/3 +// <3=> 32MHz/4 +// <4=> 32MHz/5 +// <5=> 32MHz/6 +// <6=> 32MHz/7 +// <7=> 32MHz/8 +// <8=> 32MHz/9 +// <9=> 32MHz/10 +// <10=> 32MHz/11 +// <11=> 32MHz/12 +// <12=> 32MHz/13 +// <13=> 32MHz/14 +// <14=> 32MHz/15 +// <15=> 32MHz/16 + +#ifndef NRFX_QSPI_CONFIG_FREQUENCY +#define NRFX_QSPI_CONFIG_FREQUENCY 15 +#endif + +// NRFX_QSPI_PIN_SCK - SCK pin value. +#ifndef NRFX_QSPI_PIN_SCK +#define NRFX_QSPI_PIN_SCK NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_PIN_CSN - CSN pin value. +#ifndef NRFX_QSPI_PIN_CSN +#define NRFX_QSPI_PIN_CSN NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_PIN_IO0 - IO0 pin value. +#ifndef NRFX_QSPI_PIN_IO0 +#define NRFX_QSPI_PIN_IO0 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_PIN_IO1 - IO1 pin value. +#ifndef NRFX_QSPI_PIN_IO1 +#define NRFX_QSPI_PIN_IO1 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_PIN_IO2 - IO2 pin value. +#ifndef NRFX_QSPI_PIN_IO2 +#define NRFX_QSPI_PIN_IO2 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_PIN_IO3 - IO3 pin value. +#ifndef NRFX_QSPI_PIN_IO3 +#define NRFX_QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// NRFX_QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_QSPI_CONFIG_IRQ_PRIORITY +#define NRFX_QSPI_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// NRFX_RNG_ENABLED - nrfx_rng - RNG peripheral driver +//========================================================== +#ifndef NRFX_RNG_ENABLED +#define NRFX_RNG_ENABLED 1 +#endif +// NRFX_RNG_CONFIG_ERROR_CORRECTION - Error correction + + +#ifndef NRFX_RNG_CONFIG_ERROR_CORRECTION +#define NRFX_RNG_CONFIG_ERROR_CORRECTION 1 +#endif + +// NRFX_RNG_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_RNG_CONFIG_IRQ_PRIORITY +#define NRFX_RNG_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_RNG_CONFIG_LOG_ENABLED +#define NRFX_RNG_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_RNG_CONFIG_LOG_LEVEL +#define NRFX_RNG_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_RNG_CONFIG_INFO_COLOR +#define NRFX_RNG_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_RNG_CONFIG_DEBUG_COLOR +#define NRFX_RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_RTC_ENABLED - nrfx_rtc - RTC peripheral driver +//========================================================== +#ifndef NRFX_RTC_ENABLED +#define NRFX_RTC_ENABLED 0 +#endif +// NRFX_RTC0_ENABLED - Enable RTC0 instance + + +#ifndef NRFX_RTC0_ENABLED +#define NRFX_RTC0_ENABLED 0 +#endif + +// NRFX_RTC1_ENABLED - Enable RTC1 instance + + +#ifndef NRFX_RTC1_ENABLED +#define NRFX_RTC1_ENABLED 0 +#endif + +// NRFX_RTC2_ENABLED - Enable RTC2 instance + + +#ifndef NRFX_RTC2_ENABLED +#define NRFX_RTC2_ENABLED 0 +#endif + +// NRFX_RTC_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt +#ifndef NRFX_RTC_MAXIMUM_LATENCY_US +#define NRFX_RTC_MAXIMUM_LATENCY_US 2000 +#endif + +// NRFX_RTC_DEFAULT_CONFIG_FREQUENCY - Frequency <16-32768> + + +#ifndef NRFX_RTC_DEFAULT_CONFIG_FREQUENCY +#define NRFX_RTC_DEFAULT_CONFIG_FREQUENCY 32768 +#endif + +// NRFX_RTC_DEFAULT_CONFIG_RELIABLE - Ensures safe compare event triggering + + +#ifndef NRFX_RTC_DEFAULT_CONFIG_RELIABLE +#define NRFX_RTC_DEFAULT_CONFIG_RELIABLE 0 +#endif + +// NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_RTC_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_RTC_CONFIG_LOG_ENABLED +#define NRFX_RTC_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_RTC_CONFIG_LOG_LEVEL +#define NRFX_RTC_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_RTC_CONFIG_INFO_COLOR +#define NRFX_RTC_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_RTC_CONFIG_DEBUG_COLOR +#define NRFX_RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_SAADC_ENABLED - nrfx_saadc - SAADC peripheral driver +//========================================================== +#ifndef NRFX_SAADC_ENABLED +#define NRFX_SAADC_ENABLED 0 +#endif +// NRFX_SAADC_CONFIG_RESOLUTION - Resolution + +// <0=> 8 bit +// <1=> 10 bit +// <2=> 12 bit +// <3=> 14 bit + +#ifndef NRFX_SAADC_CONFIG_RESOLUTION +#define NRFX_SAADC_CONFIG_RESOLUTION 1 +#endif + +// NRFX_SAADC_CONFIG_OVERSAMPLE - Sample period + +// <0=> Disabled +// <1=> 2x +// <2=> 4x +// <3=> 8x +// <4=> 16x +// <5=> 32x +// <6=> 64x +// <7=> 128x +// <8=> 256x + +#ifndef NRFX_SAADC_CONFIG_OVERSAMPLE +#define NRFX_SAADC_CONFIG_OVERSAMPLE 0 +#endif + +// NRFX_SAADC_CONFIG_LP_MODE - Enabling low power mode + + +#ifndef NRFX_SAADC_CONFIG_LP_MODE +#define NRFX_SAADC_CONFIG_LP_MODE 0 +#endif + +// NRFX_SAADC_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_SAADC_CONFIG_IRQ_PRIORITY +#define NRFX_SAADC_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SAADC_CONFIG_LOG_ENABLED +#define NRFX_SAADC_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SAADC_CONFIG_LOG_LEVEL +#define NRFX_SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SAADC_CONFIG_INFO_COLOR +#define NRFX_SAADC_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SAADC_CONFIG_DEBUG_COLOR +#define NRFX_SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_SPIM_ENABLED - nrfx_spim - SPIM peripheral driver +//========================================================== +#ifndef NRFX_SPIM_ENABLED +#define NRFX_SPIM_ENABLED 1 +#endif +// NRFX_SPIM0_ENABLED - Enable SPIM0 instance + + +#ifndef NRFX_SPIM0_ENABLED +#define NRFX_SPIM0_ENABLED 0 +#endif + +// NRFX_SPIM1_ENABLED - Enable SPIM1 instance + + +#ifndef NRFX_SPIM1_ENABLED +#define NRFX_SPIM1_ENABLED 0 +#endif + +// NRFX_SPIM2_ENABLED - Enable SPIM2 instance + + +#ifndef NRFX_SPIM2_ENABLED +#define NRFX_SPIM2_ENABLED 0 +#endif + +// NRFX_SPIM3_ENABLED - Enable SPIM3 instance + + +#ifndef NRFX_SPIM3_ENABLED +#define NRFX_SPIM3_ENABLED 0 +#endif + +// NRFX_SPIM_EXTENDED_ENABLED - Enable extended SPIM features + + +#ifndef NRFX_SPIM_EXTENDED_ENABLED +#define NRFX_SPIM_EXTENDED_ENABLED 0 +#endif + +// NRFX_SPIM_MISO_PULL_CFG - MISO pin pull configuration. + +// <0=> NRF_GPIO_PIN_NOPULL +// <1=> NRF_GPIO_PIN_PULLDOWN +// <3=> NRF_GPIO_PIN_PULLUP + +#ifndef NRFX_SPIM_MISO_PULL_CFG +#define NRFX_SPIM_MISO_PULL_CFG 1 +#endif + +// NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_SPIM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SPIM_CONFIG_LOG_ENABLED +#define NRFX_SPIM_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SPIM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SPIM_CONFIG_LOG_LEVEL +#define NRFX_SPIM_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SPIM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIM_CONFIG_INFO_COLOR +#define NRFX_SPIM_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SPIM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIM_CONFIG_DEBUG_COLOR +#define NRFX_SPIM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_SPIS_ENABLED - nrfx_spis - SPIS peripheral driver +//========================================================== +#ifndef NRFX_SPIS_ENABLED +#define NRFX_SPIS_ENABLED 0 +#endif +// NRFX_SPIS0_ENABLED - Enable SPIS0 instance + + +#ifndef NRFX_SPIS0_ENABLED +#define NRFX_SPIS0_ENABLED 0 +#endif + +// NRFX_SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef NRFX_SPIS1_ENABLED +#define NRFX_SPIS1_ENABLED 0 +#endif + +// NRFX_SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef NRFX_SPIS2_ENABLED +#define NRFX_SPIS2_ENABLED 0 +#endif + +// NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef NRFX_SPIS_DEFAULT_DEF +#define NRFX_SPIS_DEFAULT_DEF 255 +#endif + +// NRFX_SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef NRFX_SPIS_DEFAULT_ORC +#define NRFX_SPIS_DEFAULT_ORC 255 +#endif + +// NRFX_SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SPIS_CONFIG_LOG_ENABLED +#define NRFX_SPIS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SPIS_CONFIG_LOG_LEVEL +#define NRFX_SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIS_CONFIG_INFO_COLOR +#define NRFX_SPIS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPIS_CONFIG_DEBUG_COLOR +#define NRFX_SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_SPI_ENABLED - nrfx_spi - SPI peripheral driver +//========================================================== +#ifndef NRFX_SPI_ENABLED +#define NRFX_SPI_ENABLED 1 +#endif +// NRFX_SPI0_ENABLED - Enable SPI0 instance + + +#ifndef NRFX_SPI0_ENABLED +#define NRFX_SPI0_ENABLED 0 +#endif + +// NRFX_SPI1_ENABLED - Enable SPI1 instance + + +#ifndef NRFX_SPI1_ENABLED +#define NRFX_SPI1_ENABLED 0 +#endif + +// NRFX_SPI2_ENABLED - Enable SPI2 instance + + +#ifndef NRFX_SPI2_ENABLED +#define NRFX_SPI2_ENABLED 0 +#endif + +// NRFX_SPI_MISO_PULL_CFG - MISO pin pull configuration. + +// <0=> NRF_GPIO_PIN_NOPULL +// <1=> NRF_GPIO_PIN_PULLDOWN +// <3=> NRF_GPIO_PIN_PULLUP + +#ifndef NRFX_SPI_MISO_PULL_CFG +#define NRFX_SPI_MISO_PULL_CFG 1 +#endif + +// NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SPI_CONFIG_LOG_ENABLED +#define NRFX_SPI_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SPI_CONFIG_LOG_LEVEL +#define NRFX_SPI_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPI_CONFIG_INFO_COLOR +#define NRFX_SPI_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SPI_CONFIG_DEBUG_COLOR +#define NRFX_SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_SWI_ENABLED - nrfx_swi - SWI/EGU peripheral allocator +//========================================================== +#ifndef NRFX_SWI_ENABLED +#define NRFX_SWI_ENABLED 0 +#endif +// NRFX_EGU_ENABLED - Enable EGU support + + +#ifndef NRFX_EGU_ENABLED +#define NRFX_EGU_ENABLED 0 +#endif + +// NRFX_SWI0_DISABLED - Exclude SWI0 from being utilized by the driver + + +#ifndef NRFX_SWI0_DISABLED +#define NRFX_SWI0_DISABLED 0 +#endif + +// NRFX_SWI1_DISABLED - Exclude SWI1 from being utilized by the driver + + +#ifndef NRFX_SWI1_DISABLED +#define NRFX_SWI1_DISABLED 0 +#endif + +// NRFX_SWI2_DISABLED - Exclude SWI2 from being utilized by the driver + + +#ifndef NRFX_SWI2_DISABLED +#define NRFX_SWI2_DISABLED 0 +#endif + +// NRFX_SWI3_DISABLED - Exclude SWI3 from being utilized by the driver + + +#ifndef NRFX_SWI3_DISABLED +#define NRFX_SWI3_DISABLED 0 +#endif + +// NRFX_SWI4_DISABLED - Exclude SWI4 from being utilized by the driver + + +#ifndef NRFX_SWI4_DISABLED +#define NRFX_SWI4_DISABLED 0 +#endif + +// NRFX_SWI5_DISABLED - Exclude SWI5 from being utilized by the driver + + +#ifndef NRFX_SWI5_DISABLED +#define NRFX_SWI5_DISABLED 0 +#endif + +// NRFX_SWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_SWI_CONFIG_LOG_ENABLED +#define NRFX_SWI_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_SWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_SWI_CONFIG_LOG_LEVEL +#define NRFX_SWI_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_SWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SWI_CONFIG_INFO_COLOR +#define NRFX_SWI_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_SWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_SWI_CONFIG_DEBUG_COLOR +#define NRFX_SWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_TIMER_ENABLED - nrfx_timer - TIMER periperal driver +//========================================================== +#ifndef NRFX_TIMER_ENABLED +#define NRFX_TIMER_ENABLED 0 +#endif +// NRFX_TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef NRFX_TIMER0_ENABLED +#define NRFX_TIMER0_ENABLED 0 +#endif + +// NRFX_TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef NRFX_TIMER1_ENABLED +#define NRFX_TIMER1_ENABLED 0 +#endif + +// NRFX_TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef NRFX_TIMER2_ENABLED +#define NRFX_TIMER2_ENABLED 0 +#endif + +// NRFX_TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef NRFX_TIMER3_ENABLED +#define NRFX_TIMER3_ENABLED 0 +#endif + +// NRFX_TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef NRFX_TIMER4_ENABLED +#define NRFX_TIMER4_ENABLED 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_MODE +#define NRFX_TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define NRFX_TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_TIMER_CONFIG_LOG_ENABLED +#define NRFX_TIMER_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_TIMER_CONFIG_LOG_LEVEL +#define NRFX_TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TIMER_CONFIG_INFO_COLOR +#define NRFX_TIMER_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TIMER_CONFIG_DEBUG_COLOR +#define NRFX_TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_TWIM_ENABLED - nrfx_twim - TWIM peripheral driver +//========================================================== +#ifndef NRFX_TWIM_ENABLED +#define NRFX_TWIM_ENABLED 0 +#endif +// NRFX_TWIM0_ENABLED - Enable TWIM0 instance + + +#ifndef NRFX_TWIM0_ENABLED +#define NRFX_TWIM0_ENABLED 0 +#endif + +// NRFX_TWIM1_ENABLED - Enable TWIM1 instance + + +#ifndef NRFX_TWIM1_ENABLED +#define NRFX_TWIM1_ENABLED 0 +#endif + +// NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define NRFX_TWIM_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWIM_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_TWIM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_TWIM_CONFIG_LOG_ENABLED +#define NRFX_TWIM_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_TWIM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_TWIM_CONFIG_LOG_LEVEL +#define NRFX_TWIM_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_TWIM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWIM_CONFIG_INFO_COLOR +#define NRFX_TWIM_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_TWIM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWIM_CONFIG_DEBUG_COLOR +#define NRFX_TWIM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_TWIS_ENABLED - nrfx_twis - TWIS peripheral driver +//========================================================== +#ifndef NRFX_TWIS_ENABLED +#define NRFX_TWIS_ENABLED 0 +#endif +// NRFX_TWIS0_ENABLED - Enable TWIS0 instance + + +#ifndef NRFX_TWIS0_ENABLED +#define NRFX_TWIS0_ENABLED 0 +#endif + +// NRFX_TWIS1_ENABLED - Enable TWIS1 instance + + +#ifndef NRFX_TWIS1_ENABLED +#define NRFX_TWIS1_ENABLED 0 +#endif + +// NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY - Assume that any instance would be initialized only once + + +// Optimization flag. Registers used by TWIS are shared by other peripherals. Normally, during initialization driver tries to clear all registers to known state before doing the initialization itself. This gives initialization safe procedure, no matter when it would be called. If you activate TWIS only once and do never uninitialize it - set this flag to 1 what gives more optimal code. + +#ifndef NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define NRFX_TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +#endif + +// NRFX_TWIS_NO_SYNC_MODE - Remove support for synchronous mode + + +// Synchronous mode would be used in specific situations. And it uses some additional code and data memory to safely process state machine by polling it in status functions. If this functionality is not required it may be disabled to free some resources. + +#ifndef NRFX_TWIS_NO_SYNC_MODE +#define NRFX_TWIS_NO_SYNC_MODE 0 +#endif + +// NRFX_TWIS_DEFAULT_CONFIG_ADDR0 - Address0 +#ifndef NRFX_TWIS_DEFAULT_CONFIG_ADDR0 +#define NRFX_TWIS_DEFAULT_CONFIG_ADDR0 0 +#endif + +// NRFX_TWIS_DEFAULT_CONFIG_ADDR1 - Address1 +#ifndef NRFX_TWIS_DEFAULT_CONFIG_ADDR1 +#define NRFX_TWIS_DEFAULT_CONFIG_ADDR1 0 +#endif + +// NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL - SCL pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL +#define NRFX_TWIS_DEFAULT_CONFIG_SCL_PULL 0 +#endif + +// NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL - SDA pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL +#define NRFX_TWIS_DEFAULT_CONFIG_SDA_PULL 0 +#endif + +// NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_TWIS_CONFIG_LOG_ENABLED +#define NRFX_TWIS_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_TWIS_CONFIG_LOG_LEVEL +#define NRFX_TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWIS_CONFIG_INFO_COLOR +#define NRFX_TWIS_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWIS_CONFIG_DEBUG_COLOR +#define NRFX_TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_TWI_ENABLED - nrfx_twi - TWI peripheral driver +//========================================================== +#ifndef NRFX_TWI_ENABLED +#define NRFX_TWI_ENABLED 0 +#endif +// NRFX_TWI0_ENABLED - Enable TWI0 instance + + +#ifndef NRFX_TWI0_ENABLED +#define NRFX_TWI0_ENABLED 0 +#endif + +// NRFX_TWI1_ENABLED - Enable TWI1 instance + + +#ifndef NRFX_TWI1_ENABLED +#define NRFX_TWI1_ENABLED 0 +#endif + +// NRFX_TWI_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef NRFX_TWI_DEFAULT_CONFIG_FREQUENCY +#define NRFX_TWI_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define NRFX_TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_TWI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_TWI_CONFIG_LOG_ENABLED +#define NRFX_TWI_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_TWI_CONFIG_LOG_LEVEL +#define NRFX_TWI_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWI_CONFIG_INFO_COLOR +#define NRFX_TWI_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_TWI_CONFIG_DEBUG_COLOR +#define NRFX_TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UARTE_ENABLED - nrfx_uarte - UARTE peripheral driver +//========================================================== +#ifndef NRFX_UARTE_ENABLED +#define NRFX_UARTE_ENABLED 1 +#endif +// NRFX_UARTE0_ENABLED - Enable UARTE0 instance +#ifndef NRFX_UARTE0_ENABLED +#define NRFX_UARTE0_ENABLED 0 +#endif + +// NRFX_UARTE1_ENABLED - Enable UARTE1 instance +#ifndef NRFX_UARTE1_ENABLED +#define NRFX_UARTE1_ENABLED 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_HWFC +#define NRFX_UARTE_DEFAULT_CONFIG_HWFC 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_PARITY +#define NRFX_UARTE_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <8388608=> 31250 baud +// <10289152=> 38400 baud +// <15007744=> 56000 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UARTE_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UARTE_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UARTE_CONFIG_LOG_ENABLED +#define NRFX_UARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UARTE_CONFIG_LOG_LEVEL +#define NRFX_UARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_INFO_COLOR +#define NRFX_UARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UARTE_CONFIG_DEBUG_COLOR +#define NRFX_UARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_UART_ENABLED - nrfx_uart - UART peripheral driver +//========================================================== +#ifndef NRFX_UART_ENABLED +#define NRFX_UART_ENABLED 1 +#endif +// NRFX_UART0_ENABLED - Enable UART0 instance +#ifndef NRFX_UART0_ENABLED +#define NRFX_UART0_ENABLED 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef NRFX_UART_DEFAULT_CONFIG_HWFC +#define NRFX_UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef NRFX_UART_DEFAULT_CONFIG_PARITY +#define NRFX_UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// NRFX_UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3866624=> 14400 baud +// <5152768=> 19200 baud +// <7729152=> 28800 baud +// <8388608=> 31250 baud +// <10309632=> 38400 baud +// <15007744=> 56000 baud +// <15462400=> 57600 baud +// <20615168=> 76800 baud +// <30924800=> 115200 baud +// <61845504=> 230400 baud +// <67108864=> 250000 baud +// <123695104=> 460800 baud +// <247386112=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef NRFX_UART_DEFAULT_CONFIG_BAUDRATE +#define NRFX_UART_DEFAULT_CONFIG_BAUDRATE 30924800 +#endif + +// NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_UART_CONFIG_LOG_ENABLED +#define NRFX_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_UART_CONFIG_LOG_LEVEL +#define NRFX_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_INFO_COLOR +#define NRFX_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_UART_CONFIG_DEBUG_COLOR +#define NRFX_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRFX_USBD_ENABLED - nrfx_usbd - USBD peripheral driver +//========================================================== +#ifndef NRFX_USBD_ENABLED +#define NRFX_USBD_ENABLED 0 +#endif +// NRFX_USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_USBD_CONFIG_IRQ_PRIORITY +#define NRFX_USBD_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_USBD_CONFIG_DMASCHEDULER_MODE - USBD DMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef NRFX_USBD_CONFIG_DMASCHEDULER_MODE +#define NRFX_USBD_CONFIG_DMASCHEDULER_MODE 0 +#endif + +// NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST - Give priority to isochronous transfers + + +// This option gives priority to isochronous transfers. +// Enabling it assures that isochronous transfers are always processed, +// even if multiple other transfers are pending. +// Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm +// function is called, so the option is independent of the algorithm chosen. + +#ifndef NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST +#define NRFX_USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1 +#endif + +// NRFX_USBD_CONFIG_ISO_IN_ZLP - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready + + +// If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent. +// Else, there will be no response. + +#ifndef NRFX_USBD_CONFIG_ISO_IN_ZLP +#define NRFX_USBD_CONFIG_ISO_IN_ZLP 0 +#endif + +// NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211 - Use workaround for anomaly 211 + + +// If set, workaround for anomaly 211 will be enabled. +// Anomaly 211 - Device remains in SUSPEND too long when host resumes +// bus activity (sending SOF packets) without a RESUME condition. + +#ifndef NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211 +#define NRFX_USBD_USE_WORKAROUND_FOR_ANOMALY_211 0 +#endif + +// + +// NRFX_WDT_ENABLED - nrfx_wdt - WDT peripheral driver +//========================================================== +#ifndef NRFX_WDT_ENABLED +#define NRFX_WDT_ENABLED 0 +#endif +// NRFX_WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode + +// <1=> Run in SLEEP, Pause in HALT +// <8=> Pause in SLEEP, Run in HALT +// <9=> Run in SLEEP and HALT +// <0=> Pause in SLEEP and HALT + +#ifndef NRFX_WDT_CONFIG_BEHAVIOUR +#define NRFX_WDT_CONFIG_BEHAVIOUR 1 +#endif + +// NRFX_WDT_CONFIG_RELOAD_VALUE - Reload value in ms <1-131072000> + + +#ifndef NRFX_WDT_CONFIG_RELOAD_VALUE +#define NRFX_WDT_CONFIG_RELOAD_VALUE 2000 +#endif + +// NRFX_WDT_CONFIG_NO_IRQ - Remove WDT IRQ handling from WDT driver + +// <0=> Include WDT IRQ handling +// <1=> Remove WDT IRQ handling + +#ifndef NRFX_WDT_CONFIG_NO_IRQ +#define NRFX_WDT_CONFIG_NO_IRQ 0 +#endif + +// NRFX_WDT_CONFIG_IRQ_PRIORITY - Interrupt priority + +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef NRFX_WDT_CONFIG_IRQ_PRIORITY +#define NRFX_WDT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRFX_WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRFX_WDT_CONFIG_LOG_ENABLED +#define NRFX_WDT_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_WDT_CONFIG_LOG_LEVEL +#define NRFX_WDT_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_WDT_CONFIG_INFO_COLOR +#define NRFX_WDT_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_WDT_CONFIG_DEBUG_COLOR +#define NRFX_WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// + +// NRF_CLOCK_ENABLED - nrf_drv_clock - CLOCK peripheral driver - legacy layer +//========================================================== +#ifndef NRF_CLOCK_ENABLED +#define NRF_CLOCK_ENABLED 1 +#endif +// CLOCK_CONFIG_LF_SRC - LF Clock Source + +// <0=> RC +// <1=> XTAL +// <2=> Synth +// <131073=> External Low Swing +// <196609=> External Full Swing + +#ifndef CLOCK_CONFIG_LF_SRC +#define CLOCK_CONFIG_LF_SRC 1 +#endif + +// CLOCK_CONFIG_LF_CAL_ENABLED - Calibration enable for LF Clock Source + + +#ifndef CLOCK_CONFIG_LF_CAL_ENABLED +#define CLOCK_CONFIG_LF_CAL_ENABLED 0 +#endif + +// CLOCK_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef CLOCK_CONFIG_IRQ_PRIORITY +#define CLOCK_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// PDM_ENABLED - nrf_drv_pdm - PDM peripheral driver - legacy layer +//========================================================== +#ifndef PDM_ENABLED +#define PDM_ENABLED 0 +#endif +// PDM_CONFIG_MODE - Mode + +// <0=> Stereo +// <1=> Mono + +#ifndef PDM_CONFIG_MODE +#define PDM_CONFIG_MODE 1 +#endif + +// PDM_CONFIG_EDGE - Edge + +// <0=> Left falling +// <1=> Left rising + +#ifndef PDM_CONFIG_EDGE +#define PDM_CONFIG_EDGE 0 +#endif + +// PDM_CONFIG_CLOCK_FREQ - Clock frequency + +// <134217728=> 1000k +// <138412032=> 1032k (default) +// <142606336=> 1067k + +#ifndef PDM_CONFIG_CLOCK_FREQ +#define PDM_CONFIG_CLOCK_FREQ 138412032 +#endif + +// PDM_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PDM_CONFIG_IRQ_PRIORITY +#define PDM_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// POWER_ENABLED - nrf_drv_power - POWER peripheral driver - legacy layer +//========================================================== +#ifndef POWER_ENABLED +#define POWER_ENABLED 0 +#endif +// POWER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef POWER_CONFIG_IRQ_PRIORITY +#define POWER_CONFIG_IRQ_PRIORITY 6 +#endif + +// POWER_CONFIG_DEFAULT_DCDCEN - The default configuration of main DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCEN +#define POWER_CONFIG_DEFAULT_DCDCEN 0 +#endif + +// POWER_CONFIG_DEFAULT_DCDCENHV - The default configuration of High Voltage DCDC regulator + + +// This settings means only that components for DCDC regulator are installed and it can be enabled. + +#ifndef POWER_CONFIG_DEFAULT_DCDCENHV +#define POWER_CONFIG_DEFAULT_DCDCENHV 0 +#endif + +// + +// PPI_ENABLED - nrf_drv_ppi - PPI peripheral driver - legacy layer + + +#ifndef PPI_ENABLED +#define PPI_ENABLED 0 +#endif + +// PWM_ENABLED - nrf_drv_pwm - PWM peripheral driver - legacy layer +//========================================================== +#ifndef PWM_ENABLED +#define PWM_ENABLED 0 +#endif +// PWM_DEFAULT_CONFIG_OUT0_PIN - Out0 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT0_PIN +#define PWM_DEFAULT_CONFIG_OUT0_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT1_PIN - Out1 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT1_PIN +#define PWM_DEFAULT_CONFIG_OUT1_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT2_PIN - Out2 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT2_PIN +#define PWM_DEFAULT_CONFIG_OUT2_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_OUT3_PIN - Out3 pin <0-31> + + +#ifndef PWM_DEFAULT_CONFIG_OUT3_PIN +#define PWM_DEFAULT_CONFIG_OUT3_PIN 31 +#endif + +// PWM_DEFAULT_CONFIG_BASE_CLOCK - Base clock + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz + +#ifndef PWM_DEFAULT_CONFIG_BASE_CLOCK +#define PWM_DEFAULT_CONFIG_BASE_CLOCK 4 +#endif + +// PWM_DEFAULT_CONFIG_COUNT_MODE - Count mode + +// <0=> Up +// <1=> Up and Down + +#ifndef PWM_DEFAULT_CONFIG_COUNT_MODE +#define PWM_DEFAULT_CONFIG_COUNT_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_TOP_VALUE - Top value +#ifndef PWM_DEFAULT_CONFIG_TOP_VALUE +#define PWM_DEFAULT_CONFIG_TOP_VALUE 1000 +#endif + +// PWM_DEFAULT_CONFIG_LOAD_MODE - Load mode + +// <0=> Common +// <1=> Grouped +// <2=> Individual +// <3=> Waveform + +#ifndef PWM_DEFAULT_CONFIG_LOAD_MODE +#define PWM_DEFAULT_CONFIG_LOAD_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_STEP_MODE - Step mode + +// <0=> Auto +// <1=> Triggered + +#ifndef PWM_DEFAULT_CONFIG_STEP_MODE +#define PWM_DEFAULT_CONFIG_STEP_MODE 0 +#endif + +// PWM_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef PWM_DEFAULT_CONFIG_IRQ_PRIORITY +#define PWM_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// PWM0_ENABLED - Enable PWM0 instance + + +#ifndef PWM0_ENABLED +#define PWM0_ENABLED 0 +#endif + +// PWM1_ENABLED - Enable PWM1 instance + + +#ifndef PWM1_ENABLED +#define PWM1_ENABLED 0 +#endif + +// PWM2_ENABLED - Enable PWM2 instance + + +#ifndef PWM2_ENABLED +#define PWM2_ENABLED 0 +#endif + +// PWM3_ENABLED - Enable PWM3 instance + + +#ifndef PWM3_ENABLED +#define PWM3_ENABLED 0 +#endif + +// + +// QDEC_ENABLED - nrf_drv_qdec - QDEC peripheral driver - legacy layer +//========================================================== +#ifndef QDEC_ENABLED +#define QDEC_ENABLED 0 +#endif +// QDEC_CONFIG_REPORTPER - Report period + +// <0=> 10 Samples +// <1=> 40 Samples +// <2=> 80 Samples +// <3=> 120 Samples +// <4=> 160 Samples +// <5=> 200 Samples +// <6=> 240 Samples +// <7=> 280 Samples + +#ifndef QDEC_CONFIG_REPORTPER +#define QDEC_CONFIG_REPORTPER 0 +#endif + +// QDEC_CONFIG_SAMPLEPER - Sample period + +// <0=> 128 us +// <1=> 256 us +// <2=> 512 us +// <3=> 1024 us +// <4=> 2048 us +// <5=> 4096 us +// <6=> 8192 us +// <7=> 16384 us + +#ifndef QDEC_CONFIG_SAMPLEPER +#define QDEC_CONFIG_SAMPLEPER 7 +#endif + +// QDEC_CONFIG_PIO_A - A pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_A +#define QDEC_CONFIG_PIO_A 31 +#endif + +// QDEC_CONFIG_PIO_B - B pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_B +#define QDEC_CONFIG_PIO_B 31 +#endif + +// QDEC_CONFIG_PIO_LED - LED pin <0-31> + + +#ifndef QDEC_CONFIG_PIO_LED +#define QDEC_CONFIG_PIO_LED 31 +#endif + +// QDEC_CONFIG_LEDPRE - LED pre +#ifndef QDEC_CONFIG_LEDPRE +#define QDEC_CONFIG_LEDPRE 511 +#endif + +// QDEC_CONFIG_LEDPOL - LED polarity + +// <0=> Active low +// <1=> Active high + +#ifndef QDEC_CONFIG_LEDPOL +#define QDEC_CONFIG_LEDPOL 1 +#endif + +// QDEC_CONFIG_DBFEN - Debouncing enable + + +#ifndef QDEC_CONFIG_DBFEN +#define QDEC_CONFIG_DBFEN 0 +#endif + +// QDEC_CONFIG_SAMPLE_INTEN - Sample ready interrupt enable + + +#ifndef QDEC_CONFIG_SAMPLE_INTEN +#define QDEC_CONFIG_SAMPLE_INTEN 0 +#endif + +// QDEC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QDEC_CONFIG_IRQ_PRIORITY +#define QDEC_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// QSPI_ENABLED - nrf_drv_qspi - QSPI peripheral driver - legacy layer +//========================================================== +#ifndef QSPI_ENABLED +#define QSPI_ENABLED 0 +#endif +// QSPI_CONFIG_SCK_DELAY - tSHSL, tWHSL and tSHWL in number of 16 MHz periods (62.5 ns). <0-255> + + +#ifndef QSPI_CONFIG_SCK_DELAY +#define QSPI_CONFIG_SCK_DELAY 1 +#endif + +// QSPI_CONFIG_XIP_OFFSET - Address offset in the external memory for Execute in Place operation. +#ifndef QSPI_CONFIG_XIP_OFFSET +#define QSPI_CONFIG_XIP_OFFSET 0 +#endif + +// QSPI_CONFIG_READOC - Number of data lines and opcode used for reading. + +// <0=> FastRead +// <1=> Read2O +// <2=> Read2IO +// <3=> Read4O +// <4=> Read4IO + +#ifndef QSPI_CONFIG_READOC +#define QSPI_CONFIG_READOC 0 +#endif + +// QSPI_CONFIG_WRITEOC - Number of data lines and opcode used for writing. + +// <0=> PP +// <1=> PP2O +// <2=> PP4O +// <3=> PP4IO + +#ifndef QSPI_CONFIG_WRITEOC +#define QSPI_CONFIG_WRITEOC 0 +#endif + +// QSPI_CONFIG_ADDRMODE - Addressing mode. + +// <0=> 24bit +// <1=> 32bit + +#ifndef QSPI_CONFIG_ADDRMODE +#define QSPI_CONFIG_ADDRMODE 0 +#endif + +// QSPI_CONFIG_MODE - SPI mode. + +// <0=> Mode 0 +// <1=> Mode 1 + +#ifndef QSPI_CONFIG_MODE +#define QSPI_CONFIG_MODE 0 +#endif + +// QSPI_CONFIG_FREQUENCY - Frequency divider. + +// <0=> 32MHz/1 +// <1=> 32MHz/2 +// <2=> 32MHz/3 +// <3=> 32MHz/4 +// <4=> 32MHz/5 +// <5=> 32MHz/6 +// <6=> 32MHz/7 +// <7=> 32MHz/8 +// <8=> 32MHz/9 +// <9=> 32MHz/10 +// <10=> 32MHz/11 +// <11=> 32MHz/12 +// <12=> 32MHz/13 +// <13=> 32MHz/14 +// <14=> 32MHz/15 +// <15=> 32MHz/16 + +#ifndef QSPI_CONFIG_FREQUENCY +#define QSPI_CONFIG_FREQUENCY 15 +#endif + +// QSPI_PIN_SCK - SCK pin value. +#ifndef QSPI_PIN_SCK +#define QSPI_PIN_SCK NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_CSN - CSN pin value. +#ifndef QSPI_PIN_CSN +#define QSPI_PIN_CSN NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO0 - IO0 pin value. +#ifndef QSPI_PIN_IO0 +#define QSPI_PIN_IO0 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO1 - IO1 pin value. +#ifndef QSPI_PIN_IO1 +#define QSPI_PIN_IO1 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO2 - IO2 pin value. +#ifndef QSPI_PIN_IO2 +#define QSPI_PIN_IO2 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_PIN_IO3 - IO3 pin value. +#ifndef QSPI_PIN_IO3 +#define QSPI_PIN_IO3 NRF_QSPI_PIN_NOT_CONNECTED +#endif + +// QSPI_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef QSPI_CONFIG_IRQ_PRIORITY +#define QSPI_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// RNG_ENABLED - nrf_drv_rng - RNG peripheral driver - legacy layer +//========================================================== +#ifndef RNG_ENABLED +#define RNG_ENABLED 1 +#endif +// RNG_CONFIG_ERROR_CORRECTION - Error correction + + +#ifndef RNG_CONFIG_ERROR_CORRECTION +#define RNG_CONFIG_ERROR_CORRECTION 1 +#endif + +// RNG_CONFIG_POOL_SIZE - Pool size +#ifndef RNG_CONFIG_POOL_SIZE +#define RNG_CONFIG_POOL_SIZE 64 +#endif + +// RNG_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RNG_CONFIG_IRQ_PRIORITY +#define RNG_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// RTC_ENABLED - nrf_drv_rtc - RTC peripheral driver - legacy layer +//========================================================== +#ifndef RTC_ENABLED +#define RTC_ENABLED 0 +#endif +// RTC_DEFAULT_CONFIG_FREQUENCY - Frequency <16-32768> + + +#ifndef RTC_DEFAULT_CONFIG_FREQUENCY +#define RTC_DEFAULT_CONFIG_FREQUENCY 32768 +#endif + +// RTC_DEFAULT_CONFIG_RELIABLE - Ensures safe compare event triggering + + +#ifndef RTC_DEFAULT_CONFIG_RELIABLE +#define RTC_DEFAULT_CONFIG_RELIABLE 0 +#endif + +// RTC_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef RTC_DEFAULT_CONFIG_IRQ_PRIORITY +#define RTC_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// RTC0_ENABLED - Enable RTC0 instance + + +#ifndef RTC0_ENABLED +#define RTC0_ENABLED 0 +#endif + +// RTC1_ENABLED - Enable RTC1 instance + + +#ifndef RTC1_ENABLED +#define RTC1_ENABLED 0 +#endif + +// RTC2_ENABLED - Enable RTC2 instance + + +#ifndef RTC2_ENABLED +#define RTC2_ENABLED 0 +#endif + +// NRF_MAXIMUM_LATENCY_US - Maximum possible time[us] in highest priority interrupt +#ifndef NRF_MAXIMUM_LATENCY_US +#define NRF_MAXIMUM_LATENCY_US 2000 +#endif + +// + +// SAADC_ENABLED - nrf_drv_saadc - SAADC peripheral driver - legacy layer +//========================================================== +#ifndef SAADC_ENABLED +#define SAADC_ENABLED 0 +#endif +// SAADC_CONFIG_RESOLUTION - Resolution + +// <0=> 8 bit +// <1=> 10 bit +// <2=> 12 bit +// <3=> 14 bit + +#ifndef SAADC_CONFIG_RESOLUTION +#define SAADC_CONFIG_RESOLUTION 1 +#endif + +// SAADC_CONFIG_OVERSAMPLE - Sample period + +// <0=> Disabled +// <1=> 2x +// <2=> 4x +// <3=> 8x +// <4=> 16x +// <5=> 32x +// <6=> 64x +// <7=> 128x +// <8=> 256x + +#ifndef SAADC_CONFIG_OVERSAMPLE +#define SAADC_CONFIG_OVERSAMPLE 0 +#endif + +// SAADC_CONFIG_LP_MODE - Enabling low power mode + + +#ifndef SAADC_CONFIG_LP_MODE +#define SAADC_CONFIG_LP_MODE 0 +#endif + +// SAADC_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SAADC_CONFIG_IRQ_PRIORITY +#define SAADC_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// SPIS_ENABLED - nrf_drv_spis - SPIS peripheral driver - legacy layer +//========================================================== +#ifndef SPIS_ENABLED +#define SPIS_ENABLED 0 +#endif +// SPIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// SPIS_DEFAULT_MODE - Mode + +// <0=> MODE_0 +// <1=> MODE_1 +// <2=> MODE_2 +// <3=> MODE_3 + +#ifndef SPIS_DEFAULT_MODE +#define SPIS_DEFAULT_MODE 0 +#endif + +// SPIS_DEFAULT_BIT_ORDER - SPIS default bit order + +// <0=> MSB first +// <1=> LSB first + +#ifndef SPIS_DEFAULT_BIT_ORDER +#define SPIS_DEFAULT_BIT_ORDER 0 +#endif + +// SPIS_DEFAULT_DEF - SPIS default DEF character <0-255> + + +#ifndef SPIS_DEFAULT_DEF +#define SPIS_DEFAULT_DEF 255 +#endif + +// SPIS_DEFAULT_ORC - SPIS default ORC character <0-255> + + +#ifndef SPIS_DEFAULT_ORC +#define SPIS_DEFAULT_ORC 255 +#endif + +// SPIS0_ENABLED - Enable SPIS0 instance + + +#ifndef SPIS0_ENABLED +#define SPIS0_ENABLED 0 +#endif + +// SPIS1_ENABLED - Enable SPIS1 instance + + +#ifndef SPIS1_ENABLED +#define SPIS1_ENABLED 0 +#endif + +// SPIS2_ENABLED - Enable SPIS2 instance + + +#ifndef SPIS2_ENABLED +#define SPIS2_ENABLED 0 +#endif + +// + +// SPI_ENABLED - nrf_drv_spi - SPI/SPIM peripheral driver - legacy layer +//========================================================== +#ifndef SPI_ENABLED +#define SPI_ENABLED 1 +#endif +// SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef SPI_DEFAULT_CONFIG_IRQ_PRIORITY +#define SPI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// NRF_SPI_DRV_MISO_PULLUP_CFG - MISO PIN pull-up configuration. + +// <0=> NRF_GPIO_PIN_NOPULL +// <1=> NRF_GPIO_PIN_PULLDOWN +// <3=> NRF_GPIO_PIN_PULLUP + +#ifndef NRF_SPI_DRV_MISO_PULLUP_CFG +#define NRF_SPI_DRV_MISO_PULLUP_CFG 1 +#endif + +// SPI0_ENABLED - Enable SPI0 instance +//========================================================== +#ifndef SPI0_ENABLED +#define SPI0_ENABLED 1 +#endif +// SPI0_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI0_USE_EASY_DMA +#define SPI0_USE_EASY_DMA 1 +#endif + +// + +// SPI1_ENABLED - Enable SPI1 instance +//========================================================== +#ifndef SPI1_ENABLED +#define SPI1_ENABLED 0 +#endif +// SPI1_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI1_USE_EASY_DMA +#define SPI1_USE_EASY_DMA 1 +#endif + +// + +// SPI2_ENABLED - Enable SPI2 instance +//========================================================== +#ifndef SPI2_ENABLED +#define SPI2_ENABLED 0 +#endif +// SPI2_USE_EASY_DMA - Use EasyDMA + + +#ifndef SPI2_USE_EASY_DMA +#define SPI2_USE_EASY_DMA 1 +#endif + +// + +// + +// TIMER_ENABLED - nrf_drv_timer - TIMER periperal driver - legacy layer +//========================================================== +#ifndef TIMER_ENABLED +#define TIMER_ENABLED 0 +#endif +// TIMER_DEFAULT_CONFIG_FREQUENCY - Timer frequency if in Timer mode + +// <0=> 16 MHz +// <1=> 8 MHz +// <2=> 4 MHz +// <3=> 2 MHz +// <4=> 1 MHz +// <5=> 500 kHz +// <6=> 250 kHz +// <7=> 125 kHz +// <8=> 62.5 kHz +// <9=> 31.25 kHz + +#ifndef TIMER_DEFAULT_CONFIG_FREQUENCY +#define TIMER_DEFAULT_CONFIG_FREQUENCY 0 +#endif + +// TIMER_DEFAULT_CONFIG_MODE - Timer mode or operation + +// <0=> Timer +// <1=> Counter + +#ifndef TIMER_DEFAULT_CONFIG_MODE +#define TIMER_DEFAULT_CONFIG_MODE 0 +#endif + +// TIMER_DEFAULT_CONFIG_BIT_WIDTH - Timer counter bit width + +// <0=> 16 bit +// <1=> 8 bit +// <2=> 24 bit +// <3=> 32 bit + +#ifndef TIMER_DEFAULT_CONFIG_BIT_WIDTH +#define TIMER_DEFAULT_CONFIG_BIT_WIDTH 0 +#endif + +// TIMER_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TIMER_DEFAULT_CONFIG_IRQ_PRIORITY +#define TIMER_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// TIMER0_ENABLED - Enable TIMER0 instance + + +#ifndef TIMER0_ENABLED +#define TIMER0_ENABLED 0 +#endif + +// TIMER1_ENABLED - Enable TIMER1 instance + + +#ifndef TIMER1_ENABLED +#define TIMER1_ENABLED 0 +#endif + +// TIMER2_ENABLED - Enable TIMER2 instance + + +#ifndef TIMER2_ENABLED +#define TIMER2_ENABLED 0 +#endif + +// TIMER3_ENABLED - Enable TIMER3 instance + + +#ifndef TIMER3_ENABLED +#define TIMER3_ENABLED 0 +#endif + +// TIMER4_ENABLED - Enable TIMER4 instance + + +#ifndef TIMER4_ENABLED +#define TIMER4_ENABLED 0 +#endif + +// + +// TWIS_ENABLED - nrf_drv_twis - TWIS peripheral driver - legacy layer +//========================================================== +#ifndef TWIS_ENABLED +#define TWIS_ENABLED 0 +#endif +// TWIS0_ENABLED - Enable TWIS0 instance + + +#ifndef TWIS0_ENABLED +#define TWIS0_ENABLED 0 +#endif + +// TWIS1_ENABLED - Enable TWIS1 instance + + +#ifndef TWIS1_ENABLED +#define TWIS1_ENABLED 0 +#endif + +// TWIS_ASSUME_INIT_AFTER_RESET_ONLY - Assume that any instance would be initialized only once + + +// Optimization flag. Registers used by TWIS are shared by other peripherals. Normally, during initialization driver tries to clear all registers to known state before doing the initialization itself. This gives initialization safe procedure, no matter when it would be called. If you activate TWIS only once and do never uninitialize it - set this flag to 1 what gives more optimal code. + +#ifndef TWIS_ASSUME_INIT_AFTER_RESET_ONLY +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +#endif + +// TWIS_NO_SYNC_MODE - Remove support for synchronous mode + + +// Synchronous mode would be used in specific situations. And it uses some additional code and data memory to safely process state machine by polling it in status functions. If this functionality is not required it may be disabled to free some resources. + +#ifndef TWIS_NO_SYNC_MODE +#define TWIS_NO_SYNC_MODE 0 +#endif + +// TWIS_DEFAULT_CONFIG_ADDR0 - Address0 +#ifndef TWIS_DEFAULT_CONFIG_ADDR0 +#define TWIS_DEFAULT_CONFIG_ADDR0 0 +#endif + +// TWIS_DEFAULT_CONFIG_ADDR1 - Address1 +#ifndef TWIS_DEFAULT_CONFIG_ADDR1 +#define TWIS_DEFAULT_CONFIG_ADDR1 0 +#endif + +// TWIS_DEFAULT_CONFIG_SCL_PULL - SCL pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SCL_PULL +#define TWIS_DEFAULT_CONFIG_SCL_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_SDA_PULL - SDA pin pull configuration + +// <0=> Disabled +// <1=> Pull down +// <3=> Pull up + +#ifndef TWIS_DEFAULT_CONFIG_SDA_PULL +#define TWIS_DEFAULT_CONFIG_SDA_PULL 0 +#endif + +// TWIS_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWIS_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWIS_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// TWI_ENABLED - nrf_drv_twi - TWI/TWIM peripheral driver - legacy layer +//========================================================== +#ifndef TWI_ENABLED +#define TWI_ENABLED 0 +#endif +// TWI_DEFAULT_CONFIG_FREQUENCY - Frequency + +// <26738688=> 100k +// <67108864=> 250k +// <104857600=> 400k + +#ifndef TWI_DEFAULT_CONFIG_FREQUENCY +#define TWI_DEFAULT_CONFIG_FREQUENCY 26738688 +#endif + +// TWI_DEFAULT_CONFIG_CLR_BUS_INIT - Enables bus clearing procedure during init + + +#ifndef TWI_DEFAULT_CONFIG_CLR_BUS_INIT +#define TWI_DEFAULT_CONFIG_CLR_BUS_INIT 0 +#endif + +// TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT - Enables bus holding after uninit + + +#ifndef TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT +#define TWI_DEFAULT_CONFIG_HOLD_BUS_UNINIT 0 +#endif + +// TWI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef TWI_DEFAULT_CONFIG_IRQ_PRIORITY +#define TWI_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// TWI0_ENABLED - Enable TWI0 instance +//========================================================== +#ifndef TWI0_ENABLED +#define TWI0_ENABLED 0 +#endif +// TWI0_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI0_USE_EASY_DMA +#define TWI0_USE_EASY_DMA 0 +#endif + +// + +// TWI1_ENABLED - Enable TWI1 instance +//========================================================== +#ifndef TWI1_ENABLED +#define TWI1_ENABLED 0 +#endif +// TWI1_USE_EASY_DMA - Use EasyDMA (if present) + + +#ifndef TWI1_USE_EASY_DMA +#define TWI1_USE_EASY_DMA 0 +#endif + +// + +// + +// UART_ENABLED - nrf_drv_uart - UART/UARTE peripheral driver - legacy layer +//========================================================== +#ifndef UART_ENABLED +#define UART_ENABLED 1 +#endif +// UART_DEFAULT_CONFIG_HWFC - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef UART_DEFAULT_CONFIG_HWFC +#define UART_DEFAULT_CONFIG_HWFC 0 +#endif + +// UART_DEFAULT_CONFIG_PARITY - Parity + +// <0=> Excluded +// <14=> Included + +#ifndef UART_DEFAULT_CONFIG_PARITY +#define UART_DEFAULT_CONFIG_PARITY 0 +#endif + +// UART_DEFAULT_CONFIG_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef UART_DEFAULT_CONFIG_BAUDRATE +#define UART_DEFAULT_CONFIG_BAUDRATE 30801920 +#endif + +// UART_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef UART_DEFAULT_CONFIG_IRQ_PRIORITY +#define UART_DEFAULT_CONFIG_IRQ_PRIORITY 6 +#endif + +// UART_EASY_DMA_SUPPORT - Driver supporting EasyDMA + + +#ifndef UART_EASY_DMA_SUPPORT +#define UART_EASY_DMA_SUPPORT 1 +#endif + +// UART_LEGACY_SUPPORT - Driver supporting Legacy mode + + +#ifndef UART_LEGACY_SUPPORT +#define UART_LEGACY_SUPPORT 1 +#endif + +// UART0_ENABLED - Enable UART0 instance +//========================================================== +#ifndef UART0_ENABLED +#define UART0_ENABLED 1 +#endif +// UART0_CONFIG_USE_EASY_DMA - Default setting for using EasyDMA + + +#ifndef UART0_CONFIG_USE_EASY_DMA +#define UART0_CONFIG_USE_EASY_DMA 1 +#endif + +// + +// UART1_ENABLED - Enable UART1 instance +//========================================================== +#ifndef UART1_ENABLED +#define UART1_ENABLED 0 +#endif +// + +// + +// USBD_ENABLED - nrf_drv_usbd - Software Component +//========================================================== +#ifndef USBD_ENABLED +#define USBD_ENABLED 0 +#endif +// USBD_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef USBD_CONFIG_IRQ_PRIORITY +#define USBD_CONFIG_IRQ_PRIORITY 6 +#endif + +// USBD_CONFIG_DMASCHEDULER_MODE - USBD SMA scheduler working scheme + +// <0=> Prioritized access +// <1=> Round Robin + +#ifndef USBD_CONFIG_DMASCHEDULER_MODE +#define USBD_CONFIG_DMASCHEDULER_MODE 0 +#endif + +// USBD_CONFIG_DMASCHEDULER_ISO_BOOST - Give priority to isochronous transfers + + +// This option gives priority to isochronous transfers. +// Enabling it assures that isochronous transfers are always processed, +// even if multiple other transfers are pending. +// Isochronous endpoints are prioritized before the usbd_dma_scheduler_algorithm +// function is called, so the option is independent of the algorithm chosen. + +#ifndef USBD_CONFIG_DMASCHEDULER_ISO_BOOST +#define USBD_CONFIG_DMASCHEDULER_ISO_BOOST 1 +#endif + +// USBD_CONFIG_ISO_IN_ZLP - Respond to an IN token on ISO IN endpoint with ZLP when no data is ready + + +// If set, ISO IN endpoint will respond to an IN token with ZLP when no data is ready to be sent. +// Else, there will be no response. +// NOTE: This option does not work on Engineering A chip. + +#ifndef USBD_CONFIG_ISO_IN_ZLP +#define USBD_CONFIG_ISO_IN_ZLP 0 +#endif + +// + +// WDT_ENABLED - nrf_drv_wdt - WDT peripheral driver - legacy layer +//========================================================== +#ifndef WDT_ENABLED +#define WDT_ENABLED 0 +#endif +// WDT_CONFIG_BEHAVIOUR - WDT behavior in CPU SLEEP or HALT mode + +// <1=> Run in SLEEP, Pause in HALT +// <8=> Pause in SLEEP, Run in HALT +// <9=> Run in SLEEP and HALT +// <0=> Pause in SLEEP and HALT + +#ifndef WDT_CONFIG_BEHAVIOUR +#define WDT_CONFIG_BEHAVIOUR 1 +#endif + +// WDT_CONFIG_RELOAD_VALUE - Reload value <15-4294967295> + + +#ifndef WDT_CONFIG_RELOAD_VALUE +#define WDT_CONFIG_RELOAD_VALUE 2000 +#endif + +// WDT_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef WDT_CONFIG_IRQ_PRIORITY +#define WDT_CONFIG_IRQ_PRIORITY 6 +#endif + +// + +// +//========================================================== + +// nRF_Drivers_External + +//========================================================== +// NRF_TWI_SENSOR_ENABLED - nrf_twi_sensor - nRF TWI Sensor module + + +#ifndef NRF_TWI_SENSOR_ENABLED +#define NRF_TWI_SENSOR_ENABLED 0 +#endif + +// +//========================================================== + +// nRF_Libraries + +//========================================================== +// APP_FIFO_ENABLED - app_fifo - Software FIFO implementation + + +#ifndef APP_FIFO_ENABLED +#define APP_FIFO_ENABLED 1 +#endif + +// APP_GPIOTE_ENABLED - app_gpiote - GPIOTE events dispatcher + + +#ifndef APP_GPIOTE_ENABLED +#define APP_GPIOTE_ENABLED 0 +#endif + +// APP_PWM_ENABLED - app_pwm - PWM functionality + + +#ifndef APP_PWM_ENABLED +#define APP_PWM_ENABLED 0 +#endif + +// APP_SCHEDULER_ENABLED - app_scheduler - Events scheduler +//========================================================== +#ifndef APP_SCHEDULER_ENABLED +#define APP_SCHEDULER_ENABLED 1 +#endif +// APP_SCHEDULER_WITH_PAUSE - Enabling pause feature + + +#ifndef APP_SCHEDULER_WITH_PAUSE +#define APP_SCHEDULER_WITH_PAUSE 0 +#endif + +// APP_SCHEDULER_WITH_PROFILER - Enabling scheduler profiling + + +#ifndef APP_SCHEDULER_WITH_PROFILER +#define APP_SCHEDULER_WITH_PROFILER 0 +#endif + +// + +// APP_SDCARD_ENABLED - app_sdcard - SD/MMC card support using SPI +//========================================================== +#ifndef APP_SDCARD_ENABLED +#define APP_SDCARD_ENABLED 0 +#endif +// APP_SDCARD_SPI_INSTANCE - SPI instance used + +// <0=> 0 +// <1=> 1 +// <2=> 2 + +#ifndef APP_SDCARD_SPI_INSTANCE +#define APP_SDCARD_SPI_INSTANCE 0 +#endif + +// APP_SDCARD_FREQ_INIT - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef APP_SDCARD_FREQ_INIT +#define APP_SDCARD_FREQ_INIT 67108864 +#endif + +// APP_SDCARD_FREQ_DATA - SPI frequency + +// <33554432=> 125 kHz +// <67108864=> 250 kHz +// <134217728=> 500 kHz +// <268435456=> 1 MHz +// <536870912=> 2 MHz +// <1073741824=> 4 MHz +// <2147483648=> 8 MHz + +#ifndef APP_SDCARD_FREQ_DATA +#define APP_SDCARD_FREQ_DATA 1073741824 +#endif + +// + +// APP_TIMER_ENABLED - app_timer - Application timer functionality +//========================================================== +#ifndef APP_TIMER_ENABLED +#define APP_TIMER_ENABLED 1 +#endif +// APP_TIMER_CONFIG_RTC_FREQUENCY - Configure RTC prescaler. + +// <0=> 32768 Hz +// <1=> 16384 Hz +// <3=> 8192 Hz +// <7=> 4096 Hz +// <15=> 2048 Hz +// <31=> 1024 Hz + +#ifndef APP_TIMER_CONFIG_RTC_FREQUENCY +#define APP_TIMER_CONFIG_RTC_FREQUENCY 1 +#endif + +// APP_TIMER_CONFIG_IRQ_PRIORITY - Interrupt priority + + +// Priorities 0,2 (nRF51) and 0,1,4,5 (nRF52) are reserved for SoftDevice +// <0=> 0 (highest) +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <7=> 7 + +#ifndef APP_TIMER_CONFIG_IRQ_PRIORITY +#define APP_TIMER_CONFIG_IRQ_PRIORITY 6 +#endif + +// APP_TIMER_CONFIG_OP_QUEUE_SIZE - Capacity of timer requests queue. +// Size of the queue depends on how many timers are used +// in the system, how often timers are started and overall +// system latency. If queue size is too small app_timer calls +// will fail. + +#ifndef APP_TIMER_CONFIG_OP_QUEUE_SIZE +#define APP_TIMER_CONFIG_OP_QUEUE_SIZE 10 +#endif + +// APP_TIMER_CONFIG_USE_SCHEDULER - Enable scheduling app_timer events to app_scheduler + + +#ifndef APP_TIMER_CONFIG_USE_SCHEDULER +#define APP_TIMER_CONFIG_USE_SCHEDULER 0 +#endif + +// APP_TIMER_KEEPS_RTC_ACTIVE - Enable RTC always on + + +// If option is enabled RTC is kept running even if there is no active timers. +// This option can be used when app_timer is used for timestamping. + +#ifndef APP_TIMER_KEEPS_RTC_ACTIVE +#define APP_TIMER_KEEPS_RTC_ACTIVE 0 +#endif + +// APP_TIMER_SAFE_WINDOW_MS - Maximum possible latency (in milliseconds) of handling app_timer event. +// Maximum possible timeout that can be set is reduced by safe window. +// Example: RTC frequency 16384 Hz, maximum possible timeout 1024 seconds - APP_TIMER_SAFE_WINDOW_MS. +// Since RTC is not stopped when processor is halted in debugging session, this value +// must cover it if debugging is needed. It is possible to halt processor for APP_TIMER_SAFE_WINDOW_MS +// without corrupting app_timer behavior. + +#ifndef APP_TIMER_SAFE_WINDOW_MS +#define APP_TIMER_SAFE_WINDOW_MS 300000 +#endif + +// App Timer Legacy configuration - Legacy configuration. + +//========================================================== +// APP_TIMER_WITH_PROFILER - Enable app_timer profiling + + +#ifndef APP_TIMER_WITH_PROFILER +#define APP_TIMER_WITH_PROFILER 0 +#endif + +// APP_TIMER_CONFIG_SWI_NUMBER - Configure SWI instance used. + + +#ifndef APP_TIMER_CONFIG_SWI_NUMBER +#define APP_TIMER_CONFIG_SWI_NUMBER 0 +#endif + +// +//========================================================== + +// + +// APP_UART_ENABLED - app_uart - UART driver +//========================================================== +#ifndef APP_UART_ENABLED +#define APP_UART_ENABLED 1 +#endif +// APP_UART_DRIVER_INSTANCE - UART instance used + +// <0=> 0 + +#ifndef APP_UART_DRIVER_INSTANCE +#define APP_UART_DRIVER_INSTANCE 0 +#endif + +// + +// APP_USBD_AUDIO_ENABLED - app_usbd_audio - USB AUDIO class + + +#ifndef APP_USBD_AUDIO_ENABLED +#define APP_USBD_AUDIO_ENABLED 0 +#endif + +// APP_USBD_ENABLED - app_usbd - USB Device library +//========================================================== +#ifndef APP_USBD_ENABLED +#define APP_USBD_ENABLED 0 +#endif +// APP_USBD_VID - Vendor ID. <0x0000-0xFFFF> + + +// Note: This value is not editable in Configuration Wizard. +// Vendor ID ordered from USB IF: http://www.usb.org/developers/vendor/ + +#ifndef APP_USBD_VID +#define APP_USBD_VID 0 +#endif + +// APP_USBD_PID - Product ID. <0x0000-0xFFFF> + + +// Note: This value is not editable in Configuration Wizard. +// Selected Product ID + +#ifndef APP_USBD_PID +#define APP_USBD_PID 0 +#endif + +// APP_USBD_DEVICE_VER_MAJOR - Major device version <0-99> + + +// Major device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MAJOR +#define APP_USBD_DEVICE_VER_MAJOR 1 +#endif + +// APP_USBD_DEVICE_VER_MINOR - Minor device version <0-9> + + +// Minor device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_MINOR +#define APP_USBD_DEVICE_VER_MINOR 0 +#endif + +// APP_USBD_DEVICE_VER_SUB - Sub-minor device version <0-9> + + +// Sub-minor device version, will be converted automatically to BCD notation. Use just decimal values. + +#ifndef APP_USBD_DEVICE_VER_SUB +#define APP_USBD_DEVICE_VER_SUB 0 +#endif + +// APP_USBD_CONFIG_SELF_POWERED - Self-powered device, as opposed to bus-powered. + + +#ifndef APP_USBD_CONFIG_SELF_POWERED +#define APP_USBD_CONFIG_SELF_POWERED 1 +#endif + +// APP_USBD_CONFIG_MAX_POWER - MaxPower field in configuration descriptor in milliamps. <0-500> + + +#ifndef APP_USBD_CONFIG_MAX_POWER +#define APP_USBD_CONFIG_MAX_POWER 100 +#endif + +// APP_USBD_CONFIG_POWER_EVENTS_PROCESS - Process power events. + + +// Enable processing power events in USB event handler. + +#ifndef APP_USBD_CONFIG_POWER_EVENTS_PROCESS +#define APP_USBD_CONFIG_POWER_EVENTS_PROCESS 1 +#endif + +// APP_USBD_CONFIG_EVENT_QUEUE_ENABLE - Enable event queue. + +// This is the default configuration when all the events are placed into internal queue. +// Disable it when an external queue is used like app_scheduler or if you wish to process all events inside interrupts. +// Processing all events from the interrupt level adds requirement not to call any functions that modifies the USBD library state from the context higher than USB interrupt context. +// Functions that modify USBD state are functions for sleep, wakeup, start, stop, enable, and disable. +//========================================================== +#ifndef APP_USBD_CONFIG_EVENT_QUEUE_ENABLE +#define APP_USBD_CONFIG_EVENT_QUEUE_ENABLE 1 +#endif +// APP_USBD_CONFIG_EVENT_QUEUE_SIZE - The size of the event queue. <16-64> + + +// The size of the queue for the events that would be processed in the main loop. + +#ifndef APP_USBD_CONFIG_EVENT_QUEUE_SIZE +#define APP_USBD_CONFIG_EVENT_QUEUE_SIZE 32 +#endif + +// APP_USBD_CONFIG_SOF_HANDLING_MODE - Change SOF events handling mode. + + +// Normal queue - SOF events are pushed normally into the event queue. +// Compress queue - SOF events are counted and binded with other events or executed when the queue is empty. +// This prevents the queue from filling up with SOF events. +// Interrupt - SOF events are processed in interrupt. +// <0=> Normal queue +// <1=> Compress queue +// <2=> Interrupt + +#ifndef APP_USBD_CONFIG_SOF_HANDLING_MODE +#define APP_USBD_CONFIG_SOF_HANDLING_MODE 1 +#endif + +// + +// APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE - Provide a function that generates timestamps for logs based on the current SOF. + + +// The function app_usbd_sof_timestamp_get is implemented if the logger is enabled. +// Use it when initializing the logger. +// SOF processing is always enabled when this configuration parameter is active. +// Note: This option is configured outside of APP_USBD_CONFIG_LOG_ENABLED. +// This means that it works even if the logging in this very module is disabled. + +#ifndef APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE +#define APP_USBD_CONFIG_SOF_TIMESTAMP_PROVIDE 0 +#endif + +// APP_USBD_CONFIG_DESC_STRING_SIZE - Maximum size of the NULL-terminated string of the string descriptor. <31-254> + + +// 31 characters can be stored in the internal USB buffer used for transfers. +// Any value higher than 31 creates an additional buffer just for descriptor strings. + +#ifndef APP_USBD_CONFIG_DESC_STRING_SIZE +#define APP_USBD_CONFIG_DESC_STRING_SIZE 31 +#endif + +// APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED - Enable UTF8 conversion. + + +// Enable UTF8-encoded characters. In normal processing, only ASCII characters are available. + +#ifndef APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED +#define APP_USBD_CONFIG_DESC_STRING_UTF_ENABLED 0 +#endif + +// APP_USBD_STRINGS_LANGIDS - Supported languages identifiers. + +// Note: This value is not editable in Configuration Wizard. +// Comma-separated list of supported languages. +#ifndef APP_USBD_STRINGS_LANGIDS +#define APP_USBD_STRINGS_LANGIDS APP_USBD_LANG_AND_SUBLANG(APP_USBD_LANG_ENGLISH, APP_USBD_SUBLANG_ENGLISH_US) +#endif + +// APP_USBD_STRING_ID_MANUFACTURER - Define manufacturer string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_MANUFACTURER +#define APP_USBD_STRING_ID_MANUFACTURER 1 +#endif +// APP_USBD_STRINGS_MANUFACTURER_EXTERN - Define whether @ref APP_USBD_STRINGS_MANUFACTURER is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRINGS_MANUFACTURER_EXTERN +#define APP_USBD_STRINGS_MANUFACTURER_EXTERN 0 +#endif + +// APP_USBD_STRINGS_MANUFACTURER - String descriptor for the manufacturer name. + +// Note: This value is not editable in Configuration Wizard. +// Comma-separated list of manufacturer names for each defined language. +// Use @ref APP_USBD_STRING_DESC macro to create string descriptor from a NULL-terminated string. +// Use @ref APP_USBD_STRING_RAW8_DESC macro to create string descriptor from comma-separated uint8_t values. +// Use @ref APP_USBD_STRING_RAW16_DESC macro to create string descriptor from comma-separated uint16_t values. +// Alternatively, configure the macro to point to any internal variable pointer that already contains the descriptor. +// Setting string to NULL disables that string. +// The order of manufacturer names must be the same like in @ref APP_USBD_STRINGS_LANGIDS. +#ifndef APP_USBD_STRINGS_MANUFACTURER +#define APP_USBD_STRINGS_MANUFACTURER APP_USBD_STRING_DESC("Nordic Semiconductor") +#endif + +// + +// APP_USBD_STRING_ID_PRODUCT - Define product string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_PRODUCT +#define APP_USBD_STRING_ID_PRODUCT 2 +#endif +// APP_USBD_STRINGS_PRODUCT_EXTERN - Define whether @ref APP_USBD_STRINGS_PRODUCT is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRINGS_PRODUCT_EXTERN +#define APP_USBD_STRINGS_PRODUCT_EXTERN 0 +#endif + +// APP_USBD_STRINGS_PRODUCT - String descriptor for the product name. + +// Note: This value is not editable in Configuration Wizard. +// List of product names that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRINGS_PRODUCT +#define APP_USBD_STRINGS_PRODUCT APP_USBD_STRING_DESC("nRF52 USB Product") +#endif + +// + +// APP_USBD_STRING_ID_SERIAL - Define serial number string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_SERIAL +#define APP_USBD_STRING_ID_SERIAL 3 +#endif +// APP_USBD_STRING_SERIAL_EXTERN - Define whether @ref APP_USBD_STRING_SERIAL is created by macro or declared as a global variable. + + +#ifndef APP_USBD_STRING_SERIAL_EXTERN +#define APP_USBD_STRING_SERIAL_EXTERN 0 +#endif + +// APP_USBD_STRING_SERIAL - String descriptor for the serial number. + +// Note: This value is not editable in Configuration Wizard. +// Serial number that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRING_SERIAL +#define APP_USBD_STRING_SERIAL APP_USBD_STRING_DESC("000000000000") +#endif + +// + +// APP_USBD_STRING_ID_CONFIGURATION - Define configuration string ID. + +// Setting ID to 0 disables the string. +//========================================================== +#ifndef APP_USBD_STRING_ID_CONFIGURATION +#define APP_USBD_STRING_ID_CONFIGURATION 4 +#endif +// APP_USBD_STRING_CONFIGURATION_EXTERN - Define whether @ref APP_USBD_STRINGS_CONFIGURATION is created by macro or declared as global variable. + + +#ifndef APP_USBD_STRING_CONFIGURATION_EXTERN +#define APP_USBD_STRING_CONFIGURATION_EXTERN 0 +#endif + +// APP_USBD_STRINGS_CONFIGURATION - String descriptor for the device configuration. + +// Note: This value is not editable in Configuration Wizard. +// Configuration string that is defined the same way like in @ref APP_USBD_STRINGS_MANUFACTURER. +#ifndef APP_USBD_STRINGS_CONFIGURATION +#define APP_USBD_STRINGS_CONFIGURATION APP_USBD_STRING_DESC("Default configuration") +#endif + +// + +// APP_USBD_STRINGS_USER - Default values for user strings. + +// Note: This value is not editable in Configuration Wizard. +// This value stores all application specific user strings with the default initialization. +// The setup is done by X-macros. +// Expected macro parameters: +// @code +// X(mnemonic, [=str_idx], ...) +// @endcode +// - @c mnemonic: Mnemonic of the string descriptor that would be added to +// @ref app_usbd_string_desc_idx_t enumerator. +// - @c str_idx : String index value, can be set or left empty. +// For example, WinUSB driver requires descriptor to be present on 0xEE index. +// Then use X(USBD_STRING_WINUSB, =0xEE, (APP_USBD_STRING_DESC(...))) +// - @c ... : List of string descriptors for each defined language. +#ifndef APP_USBD_STRINGS_USER +#define APP_USBD_STRINGS_USER X(APP_USER_1, , APP_USBD_STRING_DESC("User 1")) +#endif + +// + +// APP_USBD_HID_ENABLED - app_usbd_hid - USB HID class +//========================================================== +#ifndef APP_USBD_HID_ENABLED +#define APP_USBD_HID_ENABLED 0 +#endif +// APP_USBD_HID_DEFAULT_IDLE_RATE - Default idle rate for HID class. <0-255> + + +// 0 means indefinite duration, any other value is multiplied by 4 milliseconds. Refer to Chapter 7.2.4 of HID 1.11 Specification. + +#ifndef APP_USBD_HID_DEFAULT_IDLE_RATE +#define APP_USBD_HID_DEFAULT_IDLE_RATE 0 +#endif + +// APP_USBD_HID_REPORT_IDLE_TABLE_SIZE - Size of idle rate table. <1-255> + + +// Must be higher than the highest report ID used. + +#ifndef APP_USBD_HID_REPORT_IDLE_TABLE_SIZE +#define APP_USBD_HID_REPORT_IDLE_TABLE_SIZE 4 +#endif + +// + +// APP_USBD_HID_GENERIC_ENABLED - app_usbd_hid_generic - USB HID generic + + +#ifndef APP_USBD_HID_GENERIC_ENABLED +#define APP_USBD_HID_GENERIC_ENABLED 0 +#endif + +// APP_USBD_HID_KBD_ENABLED - app_usbd_hid_kbd - USB HID keyboard + + +#ifndef APP_USBD_HID_KBD_ENABLED +#define APP_USBD_HID_KBD_ENABLED 0 +#endif + +// APP_USBD_HID_MOUSE_ENABLED - app_usbd_hid_mouse - USB HID mouse + + +#ifndef APP_USBD_HID_MOUSE_ENABLED +#define APP_USBD_HID_MOUSE_ENABLED 0 +#endif + +// APP_USBD_MSC_ENABLED - app_usbd_msc - USB MSC class + + +#ifndef APP_USBD_MSC_ENABLED +#define APP_USBD_MSC_ENABLED 0 +#endif + +// CRC16_ENABLED - crc16 - CRC16 calculation routines + + +#ifndef CRC16_ENABLED +#define CRC16_ENABLED 0 +#endif + +// CRC32_ENABLED - crc32 - CRC32 calculation routines + + +#ifndef CRC32_ENABLED +#define CRC32_ENABLED 0 +#endif + +// ECC_ENABLED - ecc - Elliptic Curve Cryptography Library + + +#ifndef ECC_ENABLED +#define ECC_ENABLED 0 +#endif + +// FDS_ENABLED - fds - Flash data storage module +//========================================================== +#ifndef FDS_ENABLED +#define FDS_ENABLED 1 +#endif +// Pages - Virtual page settings + +// Configure the number of virtual pages to use and their size. +//========================================================== +// FDS_VIRTUAL_PAGES - Number of virtual flash pages to use. +// One of the virtual pages is reserved by the system for garbage collection. +// Therefore, the minimum is two virtual pages: one page to store data and one page to be used by the system for garbage collection. +// The total amount of flash memory that is used by FDS amounts to @ref FDS_VIRTUAL_PAGES * @ref FDS_VIRTUAL_PAGE_SIZE * 4 bytes. + +#ifndef FDS_VIRTUAL_PAGES +#define FDS_VIRTUAL_PAGES 3 +#endif + +// FDS_VIRTUAL_PAGE_SIZE - The size of a virtual flash page. + + +// Expressed in number of 4-byte words. +// By default, a virtual page is the same size as a physical page. +// The size of a virtual page must be a multiple of the size of a physical page. +// <1024=> 1024 +// <2048=> 2048 + +#ifndef FDS_VIRTUAL_PAGE_SIZE +#define FDS_VIRTUAL_PAGE_SIZE 1024 +#endif + +// FDS_VIRTUAL_PAGES_RESERVED - The number of virtual flash pages that are used by other modules. +// FDS module stores its data in the last pages of the flash memory. +// By setting this value, you can move flash end address used by the FDS. +// As a result the reserved space can be used by other modules. + +#ifndef FDS_VIRTUAL_PAGES_RESERVED +#define FDS_VIRTUAL_PAGES_RESERVED 0 +#endif + +// +//========================================================== + +// Backend - Backend configuration + +// Configure which nrf_fstorage backend is used by FDS to write to flash. +//========================================================== +// FDS_BACKEND - FDS flash backend. + + +// NRF_FSTORAGE_SD uses the nrf_fstorage_sd backend implementation using the SoftDevice API. Use this if you have a SoftDevice present. +// NRF_FSTORAGE_NVMC uses the nrf_fstorage_nvmc implementation. Use this setting if you don't use the SoftDevice. +// <1=> NRF_FSTORAGE_NVMC +// <2=> NRF_FSTORAGE_SD + +#ifndef FDS_BACKEND +#define FDS_BACKEND 2 +#endif + +// +//========================================================== + +// Queue - Queue settings + +//========================================================== +// FDS_OP_QUEUE_SIZE - Size of the internal queue. +// Increase this value if you frequently get synchronous FDS_ERR_NO_SPACE_IN_QUEUES errors. + +#ifndef FDS_OP_QUEUE_SIZE +#define FDS_OP_QUEUE_SIZE 4 +#endif + +// +//========================================================== + +// CRC - CRC functionality + +//========================================================== +// FDS_CRC_CHECK_ON_READ - Enable CRC checks. + +// Save a record's CRC when it is written to flash and check it when the record is opened. +// Records with an incorrect CRC can still be 'seen' by the user using FDS functions, but they cannot be opened. +// Additionally, they will not be garbage collected until they are deleted. +//========================================================== +#ifndef FDS_CRC_CHECK_ON_READ +#define FDS_CRC_CHECK_ON_READ 0 +#endif +// FDS_CRC_CHECK_ON_WRITE - Perform a CRC check on newly written records. + + +// Perform a CRC check on newly written records. +// This setting can be used to make sure that the record data was not altered while being written to flash. +// <1=> Enabled +// <0=> Disabled + +#ifndef FDS_CRC_CHECK_ON_WRITE +#define FDS_CRC_CHECK_ON_WRITE 0 +#endif + +// + +// +//========================================================== + +// Users - Number of users + +//========================================================== +// FDS_MAX_USERS - Maximum number of callbacks that can be registered. +#ifndef FDS_MAX_USERS +#define FDS_MAX_USERS 4 +#endif + +// +//========================================================== + +// + +// HARDFAULT_HANDLER_ENABLED - hardfault_default - HardFault default handler for debugging and release + + +#ifndef HARDFAULT_HANDLER_ENABLED +#define HARDFAULT_HANDLER_ENABLED 0 +#endif + +// HCI_MEM_POOL_ENABLED - hci_mem_pool - memory pool implementation used by HCI +//========================================================== +#ifndef HCI_MEM_POOL_ENABLED +#define HCI_MEM_POOL_ENABLED 0 +#endif +// HCI_TX_BUF_SIZE - TX buffer size in bytes. +#ifndef HCI_TX_BUF_SIZE +#define HCI_TX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_SIZE - RX buffer size in bytes. +#ifndef HCI_RX_BUF_SIZE +#define HCI_RX_BUF_SIZE 600 +#endif + +// HCI_RX_BUF_QUEUE_SIZE - RX buffer queue size. +#ifndef HCI_RX_BUF_QUEUE_SIZE +#define HCI_RX_BUF_QUEUE_SIZE 4 +#endif + +// + +// HCI_SLIP_ENABLED - hci_slip - SLIP protocol implementation used by HCI +//========================================================== +#ifndef HCI_SLIP_ENABLED +#define HCI_SLIP_ENABLED 0 +#endif +// HCI_UART_BAUDRATE - Default Baudrate + +// <323584=> 1200 baud +// <643072=> 2400 baud +// <1290240=> 4800 baud +// <2576384=> 9600 baud +// <3862528=> 14400 baud +// <5152768=> 19200 baud +// <7716864=> 28800 baud +// <10289152=> 38400 baud +// <15400960=> 57600 baud +// <20615168=> 76800 baud +// <30801920=> 115200 baud +// <61865984=> 230400 baud +// <67108864=> 250000 baud +// <121634816=> 460800 baud +// <251658240=> 921600 baud +// <268435456=> 1000000 baud + +#ifndef HCI_UART_BAUDRATE +#define HCI_UART_BAUDRATE 30801920 +#endif + +// HCI_UART_FLOW_CONTROL - Hardware Flow Control + +// <0=> Disabled +// <1=> Enabled + +#ifndef HCI_UART_FLOW_CONTROL +#define HCI_UART_FLOW_CONTROL 0 +#endif + +// HCI_UART_RX_PIN - UART RX pin +#ifndef HCI_UART_RX_PIN +#define HCI_UART_RX_PIN 8 +#endif + +// HCI_UART_TX_PIN - UART TX pin +#ifndef HCI_UART_TX_PIN +#define HCI_UART_TX_PIN 6 +#endif + +// HCI_UART_RTS_PIN - UART RTS pin +#ifndef HCI_UART_RTS_PIN +#define HCI_UART_RTS_PIN 5 +#endif + +// HCI_UART_CTS_PIN - UART CTS pin +#ifndef HCI_UART_CTS_PIN +#define HCI_UART_CTS_PIN 7 +#endif + +// + +// HCI_TRANSPORT_ENABLED - hci_transport - HCI transport +//========================================================== +#ifndef HCI_TRANSPORT_ENABLED +#define HCI_TRANSPORT_ENABLED 0 +#endif +// HCI_MAX_PACKET_SIZE_IN_BITS - Maximum size of a single application packet in bits. +#ifndef HCI_MAX_PACKET_SIZE_IN_BITS +#define HCI_MAX_PACKET_SIZE_IN_BITS 8000 +#endif + +// + +// LED_SOFTBLINK_ENABLED - led_softblink - led_softblink module + + +#ifndef LED_SOFTBLINK_ENABLED +#define LED_SOFTBLINK_ENABLED 0 +#endif + +// LOW_POWER_PWM_ENABLED - low_power_pwm - low_power_pwm module + + +#ifndef LOW_POWER_PWM_ENABLED +#define LOW_POWER_PWM_ENABLED 0 +#endif + +// MEM_MANAGER_ENABLED - mem_manager - Dynamic memory allocator +//========================================================== +#ifndef MEM_MANAGER_ENABLED +#define MEM_MANAGER_ENABLED 0 +#endif +// MEMORY_MANAGER_SMALL_BLOCK_COUNT - Size of each memory blocks identified as 'small' block. <0-255> + + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT +#define MEMORY_MANAGER_SMALL_BLOCK_COUNT 1 +#endif + +// MEMORY_MANAGER_SMALL_BLOCK_SIZE - Size of each memory blocks identified as 'small' block. +// Size of each memory blocks identified as 'small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_SMALL_BLOCK_SIZE +#define MEMORY_MANAGER_SMALL_BLOCK_SIZE 32 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_COUNT - Size of each memory blocks identified as 'medium' block. <0-255> + + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT +#define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_MEDIUM_BLOCK_SIZE - Size of each memory blocks identified as 'medium' block. +// Size of each memory blocks identified as 'medium' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_MEDIUM_BLOCK_SIZE +#define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_COUNT - Size of each memory blocks identified as 'large' block. <0-255> + + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT +#define MEMORY_MANAGER_LARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_LARGE_BLOCK_SIZE - Size of each memory blocks identified as 'large' block. +// Size of each memory blocks identified as 'large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_LARGE_BLOCK_SIZE +#define MEMORY_MANAGER_LARGE_BLOCK_SIZE 256 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra large' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XLARGE_BLOCK_SIZE 1320 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra large' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT +#define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXLARGE_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra large' block. +// Size of each memory blocks identified as 'extra extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXLARGE_BLOCK_SIZE +#define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE 3444 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra small' block. +// Size of each memory blocks identified as 'extra large' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XSMALL_BLOCK_SIZE 64 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_COUNT - Size of each memory blocks identified as 'extra extra small' block. <0-255> + + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT +#define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0 +#endif + +// MEMORY_MANAGER_XXSMALL_BLOCK_SIZE - Size of each memory blocks identified as 'extra extra small' block. +// Size of each memory blocks identified as 'extra extra small' block. Memory block are recommended to be word-sized. + +#ifndef MEMORY_MANAGER_XXSMALL_BLOCK_SIZE +#define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE 32 +#endif + +// MEM_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef MEM_MANAGER_CONFIG_LOG_ENABLED +#define MEM_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// MEM_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef MEM_MANAGER_CONFIG_LOG_LEVEL +#define MEM_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// MEM_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MEM_MANAGER_CONFIG_INFO_COLOR +#define MEM_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// MEM_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MEM_MANAGER_CONFIG_DEBUG_COLOR +#define MEM_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MEM_MANAGER_DISABLE_API_PARAM_CHECK - Disable API parameter checks in the module. + + +#ifndef MEM_MANAGER_DISABLE_API_PARAM_CHECK +#define MEM_MANAGER_DISABLE_API_PARAM_CHECK 0 +#endif + +// + +// NRF_BALLOC_ENABLED - nrf_balloc - Block allocator module +//========================================================== +#ifndef NRF_BALLOC_ENABLED +#define NRF_BALLOC_ENABLED 1 +#endif +// NRF_BALLOC_CONFIG_DEBUG_ENABLED - Enables debug mode in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_DEBUG_ENABLED +#define NRF_BALLOC_CONFIG_DEBUG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS - Number of words used as head guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS +#define NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS - Number of words used as tail guard. <0-255> + + +#ifndef NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS +#define NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS 1 +#endif + +// NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED - Enables basic checks in this module. + + +#ifndef NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED +#define NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED - Enables double memory free check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED - Enables free memory corruption check in this module. + + +#ifndef NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED +#define NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED 0 +#endif + +// NRF_BALLOC_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_BALLOC_CLI_CMDS +#define NRF_BALLOC_CLI_CMDS 0 +#endif + +// + +// + +// NRF_CSENSE_ENABLED - nrf_csense - Capacitive sensor module +//========================================================== +#ifndef NRF_CSENSE_ENABLED +#define NRF_CSENSE_ENABLED 0 +#endif +// NRF_CSENSE_PAD_HYSTERESIS - Minimum value of change required to determine that a pad was touched. +#ifndef NRF_CSENSE_PAD_HYSTERESIS +#define NRF_CSENSE_PAD_HYSTERESIS 15 +#endif + +// NRF_CSENSE_PAD_DEVIATION - Minimum value measured on a pad required to take it into account while calculating the step. +#ifndef NRF_CSENSE_PAD_DEVIATION +#define NRF_CSENSE_PAD_DEVIATION 70 +#endif + +// NRF_CSENSE_MIN_PAD_VALUE - Minimum normalized value on a pad required to take its value into account. +#ifndef NRF_CSENSE_MIN_PAD_VALUE +#define NRF_CSENSE_MIN_PAD_VALUE 20 +#endif + +// NRF_CSENSE_MAX_PADS_NUMBER - Maximum number of pads used for one instance. +#ifndef NRF_CSENSE_MAX_PADS_NUMBER +#define NRF_CSENSE_MAX_PADS_NUMBER 20 +#endif + +// NRF_CSENSE_MAX_VALUE - Maximum normalized value obtained from measurement. +#ifndef NRF_CSENSE_MAX_VALUE +#define NRF_CSENSE_MAX_VALUE 1000 +#endif + +// NRF_CSENSE_OUTPUT_PIN - Output pin used by the low-level module. +// This is used when capacitive sensor does not use COMP. + +#ifndef NRF_CSENSE_OUTPUT_PIN +#define NRF_CSENSE_OUTPUT_PIN 26 +#endif + +// + +// NRF_DRV_CSENSE_ENABLED - nrf_drv_csense - Capacitive sensor low-level module +//========================================================== +#ifndef NRF_DRV_CSENSE_ENABLED +#define NRF_DRV_CSENSE_ENABLED 0 +#endif +// USE_COMP - Use the comparator to implement the capacitive sensor driver. + +// Due to Anomaly 84, COMP I_SOURCE is not functional. It has too high a varation. +//========================================================== +#ifndef USE_COMP +#define USE_COMP 0 +#endif +// TIMER0_FOR_CSENSE - First TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER0_FOR_CSENSE +#define TIMER0_FOR_CSENSE 1 +#endif + +// TIMER1_FOR_CSENSE - Second TIMER instance used by the driver (not used on nRF51). +#ifndef TIMER1_FOR_CSENSE +#define TIMER1_FOR_CSENSE 2 +#endif + +// MEASUREMENT_PERIOD - Single measurement period. +// Time of a single measurement can be calculated as +// T = (1/2)*MEASUREMENT_PERIOD*(1/f_OSC) where f_OSC = I_SOURCE / (2C*(VUP-VDOWN) ). +// I_SOURCE, VUP, and VDOWN are values used to initialize COMP and C is the capacitance of the used pad. + +#ifndef MEASUREMENT_PERIOD +#define MEASUREMENT_PERIOD 20 +#endif + +// + +// + +// NRF_FSTORAGE_ENABLED - nrf_fstorage - Flash abstraction library +//========================================================== +#ifndef NRF_FSTORAGE_ENABLED +#define NRF_FSTORAGE_ENABLED 1 +#endif +// nrf_fstorage - Common settings + +// Common settings to all fstorage implementations +//========================================================== +// NRF_FSTORAGE_PARAM_CHECK_DISABLED - Disable user input validation + + +// If selected, use ASSERT to validate user input. +// This effectively removes user input validation in production code. +// Recommended setting: OFF, only enable this setting if size is a major concern. + +#ifndef NRF_FSTORAGE_PARAM_CHECK_DISABLED +#define NRF_FSTORAGE_PARAM_CHECK_DISABLED 0 +#endif + +// +//========================================================== + +// nrf_fstorage_sd - Implementation using the SoftDevice + +// Configuration options for the fstorage implementation using the SoftDevice +//========================================================== +// NRF_FSTORAGE_SD_QUEUE_SIZE - Size of the internal queue of operations +// Increase this value if API calls frequently return the error @ref NRF_ERROR_NO_MEM. + +#ifndef NRF_FSTORAGE_SD_QUEUE_SIZE +#define NRF_FSTORAGE_SD_QUEUE_SIZE 4 +#endif + +// NRF_FSTORAGE_SD_MAX_RETRIES - Maximum number of attempts at executing an operation when the SoftDevice is busy +// Increase this value if events frequently return the @ref NRF_ERROR_TIMEOUT error. +// The SoftDevice might fail to schedule flash access due to high BLE activity. + +#ifndef NRF_FSTORAGE_SD_MAX_RETRIES +#define NRF_FSTORAGE_SD_MAX_RETRIES 8 +#endif + +// NRF_FSTORAGE_SD_MAX_WRITE_SIZE - Maximum number of bytes to be written to flash in a single operation +// This value must be a multiple of four. +// Lowering this value can increase the chances of the SoftDevice being able to execute flash operations in between radio activity. +// This value is bound by the maximum number of bytes that can be written to flash in a single call to @ref sd_flash_write. +// That is 1024 bytes for nRF51 ICs and 4096 bytes for nRF52 ICs. + +#ifndef NRF_FSTORAGE_SD_MAX_WRITE_SIZE +#define NRF_FSTORAGE_SD_MAX_WRITE_SIZE 4096 +#endif + +// +//========================================================== + +// + +// NRF_GFX_ENABLED - nrf_gfx - GFX module + + +#ifndef NRF_GFX_ENABLED +#define NRF_GFX_ENABLED 0 +#endif + +// NRF_MEMOBJ_ENABLED - nrf_memobj - Linked memory allocator module + + +#ifndef NRF_MEMOBJ_ENABLED +#define NRF_MEMOBJ_ENABLED 1 +#endif + +// NRF_PWR_MGMT_ENABLED - nrf_pwr_mgmt - Power management module +//========================================================== +#ifndef NRF_PWR_MGMT_ENABLED +#define NRF_PWR_MGMT_ENABLED 1 +#endif +// NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED - Enables pin debug in the module. + +// Selected pin will be set when CPU is in sleep mode. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED +#define NRF_PWR_MGMT_CONFIG_DEBUG_PIN_ENABLED 0 +#endif +// NRF_PWR_MGMT_SLEEP_DEBUG_PIN - Pin number + +// <0=> 0 (P0.0) +// <1=> 1 (P0.1) +// <2=> 2 (P0.2) +// <3=> 3 (P0.3) +// <4=> 4 (P0.4) +// <5=> 5 (P0.5) +// <6=> 6 (P0.6) +// <7=> 7 (P0.7) +// <8=> 8 (P0.8) +// <9=> 9 (P0.9) +// <10=> 10 (P0.10) +// <11=> 11 (P0.11) +// <12=> 12 (P0.12) +// <13=> 13 (P0.13) +// <14=> 14 (P0.14) +// <15=> 15 (P0.15) +// <16=> 16 (P0.16) +// <17=> 17 (P0.17) +// <18=> 18 (P0.18) +// <19=> 19 (P0.19) +// <20=> 20 (P0.20) +// <21=> 21 (P0.21) +// <22=> 22 (P0.22) +// <23=> 23 (P0.23) +// <24=> 24 (P0.24) +// <25=> 25 (P0.25) +// <26=> 26 (P0.26) +// <27=> 27 (P0.27) +// <28=> 28 (P0.28) +// <29=> 29 (P0.29) +// <30=> 30 (P0.30) +// <31=> 31 (P0.31) +// <32=> 32 (P1.0) +// <33=> 33 (P1.1) +// <34=> 34 (P1.2) +// <35=> 35 (P1.3) +// <36=> 36 (P1.4) +// <37=> 37 (P1.5) +// <38=> 38 (P1.6) +// <39=> 39 (P1.7) +// <40=> 40 (P1.8) +// <41=> 41 (P1.9) +// <42=> 42 (P1.10) +// <43=> 43 (P1.11) +// <44=> 44 (P1.12) +// <45=> 45 (P1.13) +// <46=> 46 (P1.14) +// <47=> 47 (P1.15) +// <4294967295=> Not connected + +#ifndef NRF_PWR_MGMT_SLEEP_DEBUG_PIN +#define NRF_PWR_MGMT_SLEEP_DEBUG_PIN 31 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED - Enables CPU usage monitor. + + +// Module will trace percentage of CPU usage in one second intervals. + +#ifndef NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED +#define NRF_PWR_MGMT_CONFIG_CPU_USAGE_MONITOR_ENABLED 0 +#endif + +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED - Enable standby timeout. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S - Standby timeout (in seconds). +// Shutdown procedure will begin no earlier than after this number of seconds. + +#ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S +#define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S 3 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED - Enables FPU event cleaning. + + +#ifndef NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED +#define NRF_PWR_MGMT_CONFIG_FPU_SUPPORT_ENABLED 1 +#endif + +// NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY - Blocked shutdown procedure will be retried every second. + + +#ifndef NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY +#define NRF_PWR_MGMT_CONFIG_AUTO_SHUTDOWN_RETRY 0 +#endif + +// NRF_PWR_MGMT_CONFIG_USE_SCHEDULER - Module will use @ref app_scheduler. + + +#ifndef NRF_PWR_MGMT_CONFIG_USE_SCHEDULER +#define NRF_PWR_MGMT_CONFIG_USE_SCHEDULER 0 +#endif + +// NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT - The number of priorities for module handlers. +// The number of stages of the shutdown process. + +#ifndef NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT +#define NRF_PWR_MGMT_CONFIG_HANDLER_PRIORITY_COUNT 3 +#endif + +// + +// NRF_QUEUE_ENABLED - nrf_queue - Queue module +//========================================================== +#ifndef NRF_QUEUE_ENABLED +#define NRF_QUEUE_ENABLED 1 +#endif +// NRF_QUEUE_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef NRF_QUEUE_CLI_CMDS +#define NRF_QUEUE_CLI_CMDS 0 +#endif + +// + +// NRF_SECTION_ITER_ENABLED - nrf_section_iter - Section iterator + + +#ifndef NRF_SECTION_ITER_ENABLED +#define NRF_SECTION_ITER_ENABLED 1 +#endif + +// NRF_SORTLIST_ENABLED - nrf_sortlist - Sorted list + + +#ifndef NRF_SORTLIST_ENABLED +#define NRF_SORTLIST_ENABLED 1 +#endif + +// NRF_SPI_MNGR_ENABLED - nrf_spi_mngr - SPI transaction manager + + +#ifndef NRF_SPI_MNGR_ENABLED +#define NRF_SPI_MNGR_ENABLED 0 +#endif + +// NRF_STRERROR_ENABLED - nrf_strerror - Library for converting error code to string. + + +#ifndef NRF_STRERROR_ENABLED +#define NRF_STRERROR_ENABLED 1 +#endif + +// NRF_TWI_MNGR_ENABLED - nrf_twi_mngr - TWI transaction manager + + +#ifndef NRF_TWI_MNGR_ENABLED +#define NRF_TWI_MNGR_ENABLED 0 +#endif + +// RETARGET_ENABLED - retarget - Retargeting stdio functions + + +#ifndef RETARGET_ENABLED +#define RETARGET_ENABLED 0 +#endif + +// SLIP_ENABLED - slip - SLIP encoding and decoding + + +#ifndef SLIP_ENABLED +#define SLIP_ENABLED 0 +#endif + +// TASK_MANAGER_ENABLED - task_manager - Task manager. +//========================================================== +#ifndef TASK_MANAGER_ENABLED +#define TASK_MANAGER_ENABLED 0 +#endif +// TASK_MANAGER_CLI_CMDS - Enable CLI commands specific to the module + + +#ifndef TASK_MANAGER_CLI_CMDS +#define TASK_MANAGER_CLI_CMDS 0 +#endif + +// TASK_MANAGER_CONFIG_MAX_TASKS - Maximum number of tasks which can be created +#ifndef TASK_MANAGER_CONFIG_MAX_TASKS +#define TASK_MANAGER_CONFIG_MAX_TASKS 2 +#endif + +// TASK_MANAGER_CONFIG_STACK_SIZE - Stack size for every task (power of 2) +#ifndef TASK_MANAGER_CONFIG_STACK_SIZE +#define TASK_MANAGER_CONFIG_STACK_SIZE 1024 +#endif + +// TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED - Enable stack profiling. + + +#ifndef TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED +#define TASK_MANAGER_CONFIG_STACK_PROFILER_ENABLED 1 +#endif + +// TASK_MANAGER_CONFIG_STACK_GUARD - Configures stack guard. + +// <0=> Disabled +// <4=> 32 bytes +// <5=> 64 bytes +// <6=> 128 bytes +// <7=> 256 bytes +// <8=> 512 bytes + +#ifndef TASK_MANAGER_CONFIG_STACK_GUARD +#define TASK_MANAGER_CONFIG_STACK_GUARD 7 +#endif + +// + +// app_button - buttons handling module + +//========================================================== +// BUTTON_ENABLED - Enables Button module + + +#ifndef BUTTON_ENABLED +#define BUTTON_ENABLED 1 +#endif + +// BUTTON_HIGH_ACCURACY_ENABLED - Enables GPIOTE high accuracy for buttons + + +#ifndef BUTTON_HIGH_ACCURACY_ENABLED +#define BUTTON_HIGH_ACCURACY_ENABLED 0 +#endif + +// +//========================================================== + +// app_usbd_cdc_acm - USB CDC ACM class + +//========================================================== +// APP_USBD_CDC_ACM_ENABLED - Enabling USBD CDC ACM Class library + + +#ifndef APP_USBD_CDC_ACM_ENABLED +#define APP_USBD_CDC_ACM_ENABLED 0 +#endif + +// APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE - Send ZLP on write with same size as endpoint + + +// If enabled, CDC ACM class will automatically send a zero length packet after transfer which has the same size as endpoint. +// This may limit throughput if a lot of binary data is sent, but in terminal mode operation it makes sure that the data is always displayed right after it is sent. + +#ifndef APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE +#define APP_USBD_CDC_ACM_ZLP_ON_EPSIZE_WRITE 1 +#endif + +// +//========================================================== + +// nrf_cli - Command line interface + +//========================================================== +// NRF_CLI_ENABLED - Enable/disable the CLI module. + + +#ifndef NRF_CLI_ENABLED +#define NRF_CLI_ENABLED 0 +#endif + +// NRF_CLI_ARGC_MAX - Maximum number of parameters passed to the command handler. +#ifndef NRF_CLI_ARGC_MAX +#define NRF_CLI_ARGC_MAX 12 +#endif + +// NRF_CLI_BUILD_IN_CMDS_ENABLED - CLI built-in commands. + + +#ifndef NRF_CLI_BUILD_IN_CMDS_ENABLED +#define NRF_CLI_BUILD_IN_CMDS_ENABLED 1 +#endif + +// NRF_CLI_CMD_BUFF_SIZE - Maximum buffer size for a single command. +#ifndef NRF_CLI_CMD_BUFF_SIZE +#define NRF_CLI_CMD_BUFF_SIZE 128 +#endif + +// NRF_CLI_ECHO_STATUS - CLI echo status. If set, echo is ON. + + +#ifndef NRF_CLI_ECHO_STATUS +#define NRF_CLI_ECHO_STATUS 1 +#endif + +// NRF_CLI_WILDCARD_ENABLED - Enable wildcard functionality for CLI commands. + + +#ifndef NRF_CLI_WILDCARD_ENABLED +#define NRF_CLI_WILDCARD_ENABLED 0 +#endif + +// NRF_CLI_METAKEYS_ENABLED - Enable additional control keys for CLI commands like ctrl+a, ctrl+e, ctrl+w, ctrl+u + + +#ifndef NRF_CLI_METAKEYS_ENABLED +#define NRF_CLI_METAKEYS_ENABLED 0 +#endif + +// NRF_CLI_PRINTF_BUFF_SIZE - Maximum print buffer size. +#ifndef NRF_CLI_PRINTF_BUFF_SIZE +#define NRF_CLI_PRINTF_BUFF_SIZE 23 +#endif + +// NRF_CLI_HISTORY_ENABLED - Enable CLI history mode. +//========================================================== +#ifndef NRF_CLI_HISTORY_ENABLED +#define NRF_CLI_HISTORY_ENABLED 1 +#endif +// NRF_CLI_HISTORY_ELEMENT_SIZE - Size of one memory object reserved for CLI history. +#ifndef NRF_CLI_HISTORY_ELEMENT_SIZE +#define NRF_CLI_HISTORY_ELEMENT_SIZE 32 +#endif + +// NRF_CLI_HISTORY_ELEMENT_COUNT - Number of history memory objects. +#ifndef NRF_CLI_HISTORY_ELEMENT_COUNT +#define NRF_CLI_HISTORY_ELEMENT_COUNT 8 +#endif + +// + +// NRF_CLI_VT100_COLORS_ENABLED - CLI VT100 colors. + + +#ifndef NRF_CLI_VT100_COLORS_ENABLED +#define NRF_CLI_VT100_COLORS_ENABLED 1 +#endif + +// NRF_CLI_STATISTICS_ENABLED - Enable CLI statistics. + + +#ifndef NRF_CLI_STATISTICS_ENABLED +#define NRF_CLI_STATISTICS_ENABLED 1 +#endif + +// NRF_CLI_LOG_BACKEND - Enable logger backend interface. + + +#ifndef NRF_CLI_LOG_BACKEND +#define NRF_CLI_LOG_BACKEND 1 +#endif + +// NRF_CLI_USES_TASK_MANAGER_ENABLED - Enable CLI to use task_manager + + +#ifndef NRF_CLI_USES_TASK_MANAGER_ENABLED +#define NRF_CLI_USES_TASK_MANAGER_ENABLED 0 +#endif + +// +//========================================================== + +// nrf_fprintf - fprintf function. + +//========================================================== +// NRF_FPRINTF_ENABLED - Enable/disable fprintf module. + + +#ifndef NRF_FPRINTF_ENABLED +#define NRF_FPRINTF_ENABLED 1 +#endif + +// NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED - For each printed LF, function will add CR. + + +#ifndef NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED +#define NRF_FPRINTF_FLAG_AUTOMATIC_CR_ON_LF_ENABLED 1 +#endif + +// NRF_FPRINTF_DOUBLE_ENABLED - Enable IEEE-754 double precision formatting. + + +#ifndef NRF_FPRINTF_DOUBLE_ENABLED +#define NRF_FPRINTF_DOUBLE_ENABLED 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_Log + +//========================================================== +// NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend +//========================================================== +#ifndef NRF_LOG_BACKEND_RTT_ENABLED +#define NRF_LOG_BACKEND_RTT_ENABLED 1 +#endif +// NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE - Size of buffer for partially processed strings. +// Size of the buffer is a trade-off between RAM usage and processing. +// if buffer is smaller then strings will often be fragmented. +// It is recommended to use size which will fit typical log and only the +// longer one will be fragmented. + +#ifndef NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE +#define NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE 64 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS - Period before retrying writing to RTT +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS +#define NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS 1 +#endif + +// NRF_LOG_BACKEND_RTT_TX_RETRY_CNT - Writing to RTT retries. +// If RTT fails to accept any new data after retries +// module assumes that host is not active and on next +// request it will perform only one write attempt. +// On successful writing, module assumes that host is active +// and scheme with retry is applied again. + +#ifndef NRF_LOG_BACKEND_RTT_TX_RETRY_CNT +#define NRF_LOG_BACKEND_RTT_TX_RETRY_CNT 3 +#endif + +// + +// NRF_LOG_ENABLED - nrf_log - Logger +//========================================================== +#ifndef NRF_LOG_ENABLED +#define NRF_LOG_ENABLED 1 +#endif +// Log message pool - Configuration of log message pool + +//========================================================== +// NRF_LOG_MSGPOOL_ELEMENT_SIZE - Size of a single element in the pool of memory objects. +// If a small value is set, then performance of logs processing +// is degraded because data is fragmented. Bigger value impacts +// RAM memory utilization. The size is set to fit a message with +// a timestamp and up to 2 arguments in a single memory object. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_SIZE +#define NRF_LOG_MSGPOOL_ELEMENT_SIZE 20 +#endif + +// NRF_LOG_MSGPOOL_ELEMENT_COUNT - Number of elements in the pool of memory objects +// If a small value is set, then it may lead to a deadlock +// in certain cases if backend has high latency and holds +// multiple messages for long time. Bigger value impacts +// RAM memory usage. + +#ifndef NRF_LOG_MSGPOOL_ELEMENT_COUNT +#define NRF_LOG_MSGPOOL_ELEMENT_COUNT 8 +#endif + +// +//========================================================== + +// NRF_LOG_ALLOW_OVERFLOW - Configures behavior when circular buffer is full. + + +// If set then oldest logs are overwritten. Otherwise a +// marker is injected informing about overflow. + +#ifndef NRF_LOG_ALLOW_OVERFLOW +#define NRF_LOG_ALLOW_OVERFLOW 1 +#endif + +// NRF_LOG_BUFSIZE - Size of the buffer for storing logs (in bytes). + + +// Must be power of 2 and multiple of 4. +// If NRF_LOG_DEFERRED = 0 then buffer size can be reduced to minimum. +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 +// <2048=> 2048 +// <4096=> 4096 +// <8192=> 8192 +// <16384=> 16384 + +#ifndef NRF_LOG_BUFSIZE +#define NRF_LOG_BUFSIZE 1024 +#endif + +// NRF_LOG_CLI_CMDS - Enable CLI commands for the module. + + +#ifndef NRF_LOG_CLI_CMDS +#define NRF_LOG_CLI_CMDS 0 +#endif + +// NRF_LOG_DEFAULT_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LOG_DEFAULT_LEVEL +#define NRF_LOG_DEFAULT_LEVEL 3 +#endif + +// NRF_LOG_DEFERRED - Enable deffered logger. + + +// Log data is buffered and can be processed in idle. + +#ifndef NRF_LOG_DEFERRED +#define NRF_LOG_DEFERRED 1 +#endif + +// NRF_LOG_FILTERS_ENABLED - Enable dynamic filtering of logs. + + +#ifndef NRF_LOG_FILTERS_ENABLED +#define NRF_LOG_FILTERS_ENABLED 0 +#endif + +// NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED - Enable use of critical region for non deffered mode when flushing logs. + + +// When enabled NRF_LOG_FLUSH is called from critical section when non deffered mode is used. +// Log output will never be corrupted as access to the log backend is exclusive +// but system will spend significant amount of time in critical section + +#ifndef NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED +#define NRF_LOG_NON_DEFFERED_CRITICAL_REGION_ENABLED 0 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_STR_PUSH_BUFFER_SIZE - Size of the buffer dedicated for strings stored using @ref NRF_LOG_PUSH. + +// <16=> 16 +// <32=> 32 +// <64=> 64 +// <128=> 128 +// <256=> 256 +// <512=> 512 +// <1024=> 1024 + +#ifndef NRF_LOG_STR_PUSH_BUFFER_SIZE +#define NRF_LOG_STR_PUSH_BUFFER_SIZE 128 +#endif + +// NRF_LOG_USES_COLORS - If enabled then ANSI escape code for colors is prefixed to every string +//========================================================== +#ifndef NRF_LOG_USES_COLORS +#define NRF_LOG_USES_COLORS 0 +#endif +// NRF_LOG_COLOR_DEFAULT - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_COLOR_DEFAULT +#define NRF_LOG_COLOR_DEFAULT 0 +#endif + +// NRF_LOG_ERROR_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_ERROR_COLOR +#define NRF_LOG_ERROR_COLOR 2 +#endif + +// NRF_LOG_WARNING_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LOG_WARNING_COLOR +#define NRF_LOG_WARNING_COLOR 4 +#endif + +// + +// NRF_LOG_USES_TIMESTAMP - Enable timestamping + +// Function for getting the timestamp is provided by the user +//========================================================== +#ifndef NRF_LOG_USES_TIMESTAMP +#define NRF_LOG_USES_TIMESTAMP 0 +#endif +// NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY - Default frequency of the timestamp (in Hz) or 0 to use app_timer frequency. +#ifndef NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY +#define NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY 0 +#endif + +// + +// nrf_log module configuration + +//========================================================== +// nrf_log in nRF_Core + +//========================================================== +// NRF_MPU_LIB_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MPU_LIB_CONFIG_LOG_ENABLED +#define NRF_MPU_LIB_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MPU_LIB_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MPU_LIB_CONFIG_LOG_LEVEL +#define NRF_MPU_LIB_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MPU_LIB_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_INFO_COLOR +#define NRF_MPU_LIB_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MPU_LIB_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MPU_LIB_CONFIG_DEBUG_COLOR +#define NRF_MPU_LIB_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_STACK_GUARD_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_STACK_GUARD_CONFIG_LOG_ENABLED +#define NRF_STACK_GUARD_CONFIG_LOG_ENABLED 0 +#endif +// NRF_STACK_GUARD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_STACK_GUARD_CONFIG_LOG_LEVEL +#define NRF_STACK_GUARD_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_STACK_GUARD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_INFO_COLOR +#define NRF_STACK_GUARD_CONFIG_INFO_COLOR 0 +#endif + +// NRF_STACK_GUARD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_STACK_GUARD_CONFIG_DEBUG_COLOR +#define NRF_STACK_GUARD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TASK_MANAGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TASK_MANAGER_CONFIG_LOG_ENABLED +#define TASK_MANAGER_CONFIG_LOG_ENABLED 0 +#endif +// TASK_MANAGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TASK_MANAGER_CONFIG_LOG_LEVEL +#define TASK_MANAGER_CONFIG_LOG_LEVEL 3 +#endif + +// TASK_MANAGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_INFO_COLOR +#define TASK_MANAGER_CONFIG_INFO_COLOR 0 +#endif + +// TASK_MANAGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TASK_MANAGER_CONFIG_DEBUG_COLOR +#define TASK_MANAGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Drivers + +//========================================================== +// CLOCK_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef CLOCK_CONFIG_LOG_ENABLED +#define CLOCK_CONFIG_LOG_ENABLED 0 +#endif +// CLOCK_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef CLOCK_CONFIG_LOG_LEVEL +#define CLOCK_CONFIG_LOG_LEVEL 3 +#endif + +// CLOCK_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_INFO_COLOR +#define CLOCK_CONFIG_INFO_COLOR 0 +#endif + +// CLOCK_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef CLOCK_CONFIG_DEBUG_COLOR +#define CLOCK_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// COMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef COMP_CONFIG_LOG_ENABLED +#define COMP_CONFIG_LOG_ENABLED 0 +#endif +// COMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef COMP_CONFIG_LOG_LEVEL +#define COMP_CONFIG_LOG_LEVEL 3 +#endif + +// COMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_INFO_COLOR +#define COMP_CONFIG_INFO_COLOR 0 +#endif + +// COMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef COMP_CONFIG_DEBUG_COLOR +#define COMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// GPIOTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef GPIOTE_CONFIG_LOG_ENABLED +#define GPIOTE_CONFIG_LOG_ENABLED 0 +#endif +// GPIOTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef GPIOTE_CONFIG_LOG_LEVEL +#define GPIOTE_CONFIG_LOG_LEVEL 3 +#endif + +// GPIOTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_INFO_COLOR +#define GPIOTE_CONFIG_INFO_COLOR 0 +#endif + +// GPIOTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef GPIOTE_CONFIG_DEBUG_COLOR +#define GPIOTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// LPCOMP_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef LPCOMP_CONFIG_LOG_ENABLED +#define LPCOMP_CONFIG_LOG_ENABLED 0 +#endif +// LPCOMP_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef LPCOMP_CONFIG_LOG_LEVEL +#define LPCOMP_CONFIG_LOG_LEVEL 3 +#endif + +// LPCOMP_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_INFO_COLOR +#define LPCOMP_CONFIG_INFO_COLOR 0 +#endif + +// LPCOMP_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef LPCOMP_CONFIG_DEBUG_COLOR +#define LPCOMP_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// MAX3421E_HOST_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef MAX3421E_HOST_CONFIG_LOG_ENABLED +#define MAX3421E_HOST_CONFIG_LOG_ENABLED 0 +#endif +// MAX3421E_HOST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef MAX3421E_HOST_CONFIG_LOG_LEVEL +#define MAX3421E_HOST_CONFIG_LOG_LEVEL 3 +#endif + +// MAX3421E_HOST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_INFO_COLOR +#define MAX3421E_HOST_CONFIG_INFO_COLOR 0 +#endif + +// MAX3421E_HOST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef MAX3421E_HOST_CONFIG_DEBUG_COLOR +#define MAX3421E_HOST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRFX_USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef NRFX_USBD_CONFIG_LOG_ENABLED +#define NRFX_USBD_CONFIG_LOG_ENABLED 0 +#endif +// NRFX_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRFX_USBD_CONFIG_LOG_LEVEL +#define NRFX_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// NRFX_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_INFO_COLOR +#define NRFX_USBD_CONFIG_INFO_COLOR 0 +#endif + +// NRFX_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRFX_USBD_CONFIG_DEBUG_COLOR +#define NRFX_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PDM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PDM_CONFIG_LOG_ENABLED +#define PDM_CONFIG_LOG_ENABLED 0 +#endif +// PDM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PDM_CONFIG_LOG_LEVEL +#define PDM_CONFIG_LOG_LEVEL 3 +#endif + +// PDM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_INFO_COLOR +#define PDM_CONFIG_INFO_COLOR 0 +#endif + +// PDM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PDM_CONFIG_DEBUG_COLOR +#define PDM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PPI_CONFIG_LOG_ENABLED +#define PPI_CONFIG_LOG_ENABLED 0 +#endif +// PPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PPI_CONFIG_LOG_LEVEL +#define PPI_CONFIG_LOG_LEVEL 3 +#endif + +// PPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_INFO_COLOR +#define PPI_CONFIG_INFO_COLOR 0 +#endif + +// PPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PPI_CONFIG_DEBUG_COLOR +#define PPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PWM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef PWM_CONFIG_LOG_ENABLED +#define PWM_CONFIG_LOG_ENABLED 0 +#endif +// PWM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PWM_CONFIG_LOG_LEVEL +#define PWM_CONFIG_LOG_LEVEL 3 +#endif + +// PWM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_INFO_COLOR +#define PWM_CONFIG_INFO_COLOR 0 +#endif + +// PWM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PWM_CONFIG_DEBUG_COLOR +#define PWM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// QDEC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef QDEC_CONFIG_LOG_ENABLED +#define QDEC_CONFIG_LOG_ENABLED 0 +#endif +// QDEC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef QDEC_CONFIG_LOG_LEVEL +#define QDEC_CONFIG_LOG_LEVEL 3 +#endif + +// QDEC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_INFO_COLOR +#define QDEC_CONFIG_INFO_COLOR 0 +#endif + +// QDEC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef QDEC_CONFIG_DEBUG_COLOR +#define QDEC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// RNG_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RNG_CONFIG_LOG_ENABLED +#define RNG_CONFIG_LOG_ENABLED 0 +#endif +// RNG_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RNG_CONFIG_LOG_LEVEL +#define RNG_CONFIG_LOG_LEVEL 3 +#endif + +// RNG_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_INFO_COLOR +#define RNG_CONFIG_INFO_COLOR 0 +#endif + +// RNG_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RNG_CONFIG_DEBUG_COLOR +#define RNG_CONFIG_DEBUG_COLOR 0 +#endif + +// RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED - Enables logging of random numbers. + + +#ifndef RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED +#define RNG_CONFIG_RANDOM_NUMBER_LOG_ENABLED 0 +#endif + +// + +// RTC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef RTC_CONFIG_LOG_ENABLED +#define RTC_CONFIG_LOG_ENABLED 0 +#endif +// RTC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef RTC_CONFIG_LOG_LEVEL +#define RTC_CONFIG_LOG_LEVEL 3 +#endif + +// RTC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_INFO_COLOR +#define RTC_CONFIG_INFO_COLOR 0 +#endif + +// RTC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef RTC_CONFIG_DEBUG_COLOR +#define RTC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SAADC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SAADC_CONFIG_LOG_ENABLED +#define SAADC_CONFIG_LOG_ENABLED 0 +#endif +// SAADC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SAADC_CONFIG_LOG_LEVEL +#define SAADC_CONFIG_LOG_LEVEL 3 +#endif + +// SAADC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_INFO_COLOR +#define SAADC_CONFIG_INFO_COLOR 0 +#endif + +// SAADC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SAADC_CONFIG_DEBUG_COLOR +#define SAADC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPIS_CONFIG_LOG_ENABLED +#define SPIS_CONFIG_LOG_ENABLED 0 +#endif +// SPIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPIS_CONFIG_LOG_LEVEL +#define SPIS_CONFIG_LOG_LEVEL 3 +#endif + +// SPIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_INFO_COLOR +#define SPIS_CONFIG_INFO_COLOR 0 +#endif + +// SPIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPIS_CONFIG_DEBUG_COLOR +#define SPIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// SPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SPI_CONFIG_LOG_ENABLED +#define SPI_CONFIG_LOG_ENABLED 0 +#endif +// SPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SPI_CONFIG_LOG_LEVEL +#define SPI_CONFIG_LOG_LEVEL 3 +#endif + +// SPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_INFO_COLOR +#define SPI_CONFIG_INFO_COLOR 0 +#endif + +// SPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SPI_CONFIG_DEBUG_COLOR +#define SPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TIMER_CONFIG_LOG_ENABLED +#define TIMER_CONFIG_LOG_ENABLED 0 +#endif +// TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TIMER_CONFIG_LOG_LEVEL +#define TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_INFO_COLOR +#define TIMER_CONFIG_INFO_COLOR 0 +#endif + +// TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TIMER_CONFIG_DEBUG_COLOR +#define TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWIS_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWIS_CONFIG_LOG_ENABLED +#define TWIS_CONFIG_LOG_ENABLED 0 +#endif +// TWIS_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWIS_CONFIG_LOG_LEVEL +#define TWIS_CONFIG_LOG_LEVEL 3 +#endif + +// TWIS_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_INFO_COLOR +#define TWIS_CONFIG_INFO_COLOR 0 +#endif + +// TWIS_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWIS_CONFIG_DEBUG_COLOR +#define TWIS_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// TWI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef TWI_CONFIG_LOG_ENABLED +#define TWI_CONFIG_LOG_ENABLED 0 +#endif +// TWI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef TWI_CONFIG_LOG_LEVEL +#define TWI_CONFIG_LOG_LEVEL 3 +#endif + +// TWI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_INFO_COLOR +#define TWI_CONFIG_INFO_COLOR 0 +#endif + +// TWI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef TWI_CONFIG_DEBUG_COLOR +#define TWI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef UART_CONFIG_LOG_ENABLED +#define UART_CONFIG_LOG_ENABLED 0 +#endif +// UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef UART_CONFIG_LOG_LEVEL +#define UART_CONFIG_LOG_LEVEL 3 +#endif + +// UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_INFO_COLOR +#define UART_CONFIG_INFO_COLOR 0 +#endif + +// UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef UART_CONFIG_DEBUG_COLOR +#define UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// USBD_CONFIG_LOG_ENABLED - Enable logging in the module +//========================================================== +#ifndef USBD_CONFIG_LOG_ENABLED +#define USBD_CONFIG_LOG_ENABLED 0 +#endif +// USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef USBD_CONFIG_LOG_LEVEL +#define USBD_CONFIG_LOG_LEVEL 3 +#endif + +// USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_INFO_COLOR +#define USBD_CONFIG_INFO_COLOR 0 +#endif + +// USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef USBD_CONFIG_DEBUG_COLOR +#define USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// WDT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef WDT_CONFIG_LOG_ENABLED +#define WDT_CONFIG_LOG_ENABLED 0 +#endif +// WDT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef WDT_CONFIG_LOG_LEVEL +#define WDT_CONFIG_LOG_LEVEL 3 +#endif + +// WDT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_INFO_COLOR +#define WDT_CONFIG_INFO_COLOR 0 +#endif + +// WDT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef WDT_CONFIG_DEBUG_COLOR +#define WDT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Libraries + +//========================================================== +// APP_BUTTON_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_BUTTON_CONFIG_LOG_ENABLED +#define APP_BUTTON_CONFIG_LOG_ENABLED 0 +#endif +// APP_BUTTON_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_LOG_LEVEL +#define APP_BUTTON_CONFIG_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL +#define APP_BUTTON_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_BUTTON_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_INFO_COLOR +#define APP_BUTTON_CONFIG_INFO_COLOR 0 +#endif + +// APP_BUTTON_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_BUTTON_CONFIG_DEBUG_COLOR +#define APP_BUTTON_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_TIMER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_TIMER_CONFIG_LOG_ENABLED +#define APP_TIMER_CONFIG_LOG_ENABLED 0 +#endif +// APP_TIMER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_LOG_LEVEL +#define APP_TIMER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_TIMER_CONFIG_INITIAL_LOG_LEVEL +#define APP_TIMER_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// APP_TIMER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_INFO_COLOR +#define APP_TIMER_CONFIG_INFO_COLOR 0 +#endif + +// APP_TIMER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_TIMER_CONFIG_DEBUG_COLOR +#define APP_TIMER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED +#define APP_USBD_CDC_ACM_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL +#define APP_USBD_CDC_ACM_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CDC_ACM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_INFO_COLOR +#define APP_USBD_CDC_ACM_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR +#define APP_USBD_CDC_ACM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_CONFIG_LOG_ENABLED - Enable logging in the module. +//========================================================== +#ifndef APP_USBD_CONFIG_LOG_ENABLED +#define APP_USBD_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_CONFIG_LOG_LEVEL +#define APP_USBD_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_INFO_COLOR +#define APP_USBD_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_CONFIG_DEBUG_COLOR +#define APP_USBD_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_DUMMY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_DUMMY_CONFIG_LOG_ENABLED +#define APP_USBD_DUMMY_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_DUMMY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_DUMMY_CONFIG_LOG_LEVEL +#define APP_USBD_DUMMY_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_DUMMY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_INFO_COLOR +#define APP_USBD_DUMMY_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_DUMMY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_DUMMY_CONFIG_DEBUG_COLOR +#define APP_USBD_DUMMY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_MSC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_MSC_CONFIG_LOG_ENABLED +#define APP_USBD_MSC_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_MSC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_MSC_CONFIG_LOG_LEVEL +#define APP_USBD_MSC_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_MSC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_INFO_COLOR +#define APP_USBD_MSC_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_MSC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_MSC_CONFIG_DEBUG_COLOR +#define APP_USBD_MSC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_ENABLED 0 +#endif +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_LOG_LEVEL 3 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_INFO_COLOR 0 +#endif + +// APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR +#define APP_USBD_NRF_DFU_TRIGGER_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_ATFIFO_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_ATFIFO_CONFIG_LOG_ENABLED +#define NRF_ATFIFO_CONFIG_LOG_ENABLED 0 +#endif +// NRF_ATFIFO_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_ATFIFO_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_INFO_COLOR +#define NRF_ATFIFO_CONFIG_INFO_COLOR 0 +#endif + +// NRF_ATFIFO_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_ATFIFO_CONFIG_DEBUG_COLOR +#define NRF_ATFIFO_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BALLOC_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BALLOC_CONFIG_LOG_ENABLED +#define NRF_BALLOC_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BALLOC_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_LOG_LEVEL +#define NRF_BALLOC_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL - Initial severity level if dynamic filtering is enabled. + + +// If module generates a lot of logs, initial log level can +// be decreased to prevent flooding. Severity level can be +// increased on instance basis. +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL +#define NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL 3 +#endif + +// NRF_BALLOC_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_INFO_COLOR +#define NRF_BALLOC_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BALLOC_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BALLOC_CONFIG_DEBUG_COLOR +#define NRF_BALLOC_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_EMPTY_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_EMPTY_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_QSPI_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_QSPI_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_ENABLED 0 +#endif +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_BLOCK_DEV_RAM_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_INFO_COLOR 0 +#endif + +// NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR +#define NRF_BLOCK_DEV_RAM_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_BLE_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_BLE_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_BLE_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_INFO_COLOR +#define NRF_CLI_BLE_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_BLE_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_CLI_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_CLI_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_CLI_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_CLI_UART_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_CLI_UART_CONFIG_LOG_ENABLED +#define NRF_CLI_UART_CONFIG_LOG_ENABLED 0 +#endif +// NRF_CLI_UART_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_CLI_UART_CONFIG_LOG_LEVEL +#define NRF_CLI_UART_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_CLI_UART_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_INFO_COLOR +#define NRF_CLI_UART_CONFIG_INFO_COLOR 0 +#endif + +// NRF_CLI_UART_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_CLI_UART_CONFIG_DEBUG_COLOR +#define NRF_CLI_UART_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_LIBUARTE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_LIBUARTE_CONFIG_LOG_ENABLED +#define NRF_LIBUARTE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_LIBUARTE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_LIBUARTE_CONFIG_LOG_LEVEL +#define NRF_LIBUARTE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_LIBUARTE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_INFO_COLOR +#define NRF_LIBUARTE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_LIBUARTE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_LIBUARTE_CONFIG_DEBUG_COLOR +#define NRF_LIBUARTE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_MEMOBJ_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_MEMOBJ_CONFIG_LOG_ENABLED +#define NRF_MEMOBJ_CONFIG_LOG_ENABLED 0 +#endif +// NRF_MEMOBJ_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_MEMOBJ_CONFIG_LOG_LEVEL +#define NRF_MEMOBJ_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_MEMOBJ_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_INFO_COLOR +#define NRF_MEMOBJ_CONFIG_INFO_COLOR 0 +#endif + +// NRF_MEMOBJ_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_MEMOBJ_CONFIG_DEBUG_COLOR +#define NRF_MEMOBJ_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_PWR_MGMT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_PWR_MGMT_CONFIG_LOG_ENABLED +#define NRF_PWR_MGMT_CONFIG_LOG_ENABLED 0 +#endif +// NRF_PWR_MGMT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_PWR_MGMT_CONFIG_LOG_LEVEL +#define NRF_PWR_MGMT_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_PWR_MGMT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_INFO_COLOR +#define NRF_PWR_MGMT_CONFIG_INFO_COLOR 0 +#endif + +// NRF_PWR_MGMT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_PWR_MGMT_CONFIG_DEBUG_COLOR +#define NRF_PWR_MGMT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_QUEUE_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_QUEUE_CONFIG_LOG_ENABLED +#define NRF_QUEUE_CONFIG_LOG_ENABLED 0 +#endif +// NRF_QUEUE_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_LEVEL +#define NRF_QUEUE_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL - Initial severity level if dynamic filtering is enabled + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL +#define NRF_QUEUE_CONFIG_LOG_INIT_FILTER_LEVEL 3 +#endif + +// NRF_QUEUE_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_INFO_COLOR +#define NRF_QUEUE_CONFIG_INFO_COLOR 0 +#endif + +// NRF_QUEUE_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_QUEUE_CONFIG_DEBUG_COLOR +#define NRF_QUEUE_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_ANT_LOG_ENABLED - Enable logging in SoftDevice handler (ANT) module. +//========================================================== +#ifndef NRF_SDH_ANT_LOG_ENABLED +#define NRF_SDH_ANT_LOG_ENABLED 0 +#endif +// NRF_SDH_ANT_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_ANT_LOG_LEVEL +#define NRF_SDH_ANT_LOG_LEVEL 3 +#endif + +// NRF_SDH_ANT_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_INFO_COLOR +#define NRF_SDH_ANT_INFO_COLOR 0 +#endif + +// NRF_SDH_ANT_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_ANT_DEBUG_COLOR +#define NRF_SDH_ANT_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_BLE_LOG_ENABLED - Enable logging in SoftDevice handler (BLE) module. +//========================================================== +#ifndef NRF_SDH_BLE_LOG_ENABLED +#define NRF_SDH_BLE_LOG_ENABLED 1 +#endif +// NRF_SDH_BLE_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_BLE_LOG_LEVEL +#define NRF_SDH_BLE_LOG_LEVEL 3 +#endif + +// NRF_SDH_BLE_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_INFO_COLOR +#define NRF_SDH_BLE_INFO_COLOR 0 +#endif + +// NRF_SDH_BLE_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_BLE_DEBUG_COLOR +#define NRF_SDH_BLE_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_LOG_ENABLED - Enable logging in SoftDevice handler module. +//========================================================== +#ifndef NRF_SDH_LOG_ENABLED +#define NRF_SDH_LOG_ENABLED 1 +#endif +// NRF_SDH_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_LOG_LEVEL +#define NRF_SDH_LOG_LEVEL 3 +#endif + +// NRF_SDH_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_INFO_COLOR +#define NRF_SDH_INFO_COLOR 0 +#endif + +// NRF_SDH_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_DEBUG_COLOR +#define NRF_SDH_DEBUG_COLOR 0 +#endif + +// + +// NRF_SDH_SOC_LOG_ENABLED - Enable logging in SoftDevice handler (SoC) module. +//========================================================== +#ifndef NRF_SDH_SOC_LOG_ENABLED +#define NRF_SDH_SOC_LOG_ENABLED 1 +#endif +// NRF_SDH_SOC_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SDH_SOC_LOG_LEVEL +#define NRF_SDH_SOC_LOG_LEVEL 3 +#endif + +// NRF_SDH_SOC_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_INFO_COLOR +#define NRF_SDH_SOC_INFO_COLOR 0 +#endif + +// NRF_SDH_SOC_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SDH_SOC_DEBUG_COLOR +#define NRF_SDH_SOC_DEBUG_COLOR 0 +#endif + +// + +// NRF_SORTLIST_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_SORTLIST_CONFIG_LOG_ENABLED +#define NRF_SORTLIST_CONFIG_LOG_ENABLED 0 +#endif +// NRF_SORTLIST_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_SORTLIST_CONFIG_LOG_LEVEL +#define NRF_SORTLIST_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_SORTLIST_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_INFO_COLOR +#define NRF_SORTLIST_CONFIG_INFO_COLOR 0 +#endif + +// NRF_SORTLIST_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_SORTLIST_CONFIG_DEBUG_COLOR +#define NRF_SORTLIST_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// NRF_TWI_SENSOR_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_ENABLED +#define NRF_TWI_SENSOR_CONFIG_LOG_ENABLED 0 +#endif +// NRF_TWI_SENSOR_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NRF_TWI_SENSOR_CONFIG_LOG_LEVEL +#define NRF_TWI_SENSOR_CONFIG_LOG_LEVEL 3 +#endif + +// NRF_TWI_SENSOR_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_INFO_COLOR +#define NRF_TWI_SENSOR_CONFIG_INFO_COLOR 0 +#endif + +// NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR +#define NRF_TWI_SENSOR_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// PM_LOG_ENABLED - Enable logging in Peer Manager and its submodules. +//========================================================== +#ifndef PM_LOG_ENABLED +#define PM_LOG_ENABLED 1 +#endif +// PM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef PM_LOG_LEVEL +#define PM_LOG_LEVEL 3 +#endif + +// PM_LOG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_INFO_COLOR +#define PM_LOG_INFO_COLOR 0 +#endif + +// PM_LOG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef PM_LOG_DEBUG_COLOR +#define PM_LOG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// nrf_log in nRF_Serialization + +//========================================================== +// SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED +#define SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED 0 +#endif +// SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL +#define SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL 3 +#endif + +// SER_HAL_TRANSPORT_CONFIG_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_INFO_COLOR +#define SER_HAL_TRANSPORT_CONFIG_INFO_COLOR 0 +#endif + +// SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR +#define SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR 0 +#endif + +// + +// +//========================================================== + +// +//========================================================== + +// + +// NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED - nrf_log_str_formatter - Log string formatter + + +#ifndef NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED +#define NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED 1 +#endif + +// +//========================================================== + +// nRF_NFC + +//========================================================== +// NFC_AC_REC_ENABLED - nfc_ac_rec - NFC NDEF Alternative Carrier record encoder + + +#ifndef NFC_AC_REC_ENABLED +#define NFC_AC_REC_ENABLED 0 +#endif + +// NFC_AC_REC_PARSER_ENABLED - nfc_ac_rec_parser - Alternative Carrier record parser + + +#ifndef NFC_AC_REC_PARSER_ENABLED +#define NFC_AC_REC_PARSER_ENABLED 0 +#endif + +// NFC_BLE_OOB_ADVDATA_ENABLED - nfc_ble_oob_advdata - AD data for OOB pairing encoder +//========================================================== +#ifndef NFC_BLE_OOB_ADVDATA_ENABLED +#define NFC_BLE_OOB_ADVDATA_ENABLED 0 +#endif +// ADVANCED_ADVDATA_SUPPORT - Non-mandatory AD types for BLE OOB pairing are encoded inside the NDEF message (e.g. service UUIDs) + +// <1=> Enabled +// <0=> Disabled + +#ifndef ADVANCED_ADVDATA_SUPPORT +#define ADVANCED_ADVDATA_SUPPORT 0 +#endif + +// + +// NFC_BLE_OOB_ADVDATA_PARSER_ENABLED - nfc_ble_oob_advdata_parser - BLE OOB pairing AD data parser + + +#ifndef NFC_BLE_OOB_ADVDATA_PARSER_ENABLED +#define NFC_BLE_OOB_ADVDATA_PARSER_ENABLED 0 +#endif + +// NFC_BLE_PAIR_LIB_ENABLED - nfc_ble_pair_lib - Library parameters +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_ENABLED +#define NFC_BLE_PAIR_LIB_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_BLE_PAIR_LIB_LOG_ENABLED +#define NFC_BLE_PAIR_LIB_LOG_ENABLED 0 +#endif +// NFC_BLE_PAIR_LIB_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_BLE_PAIR_LIB_LOG_LEVEL +#define NFC_BLE_PAIR_LIB_LOG_LEVEL 3 +#endif + +// NFC_BLE_PAIR_LIB_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_INFO_COLOR +#define NFC_BLE_PAIR_LIB_INFO_COLOR 0 +#endif + +// NFC_BLE_PAIR_LIB_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_BLE_PAIR_LIB_DEBUG_COLOR +#define NFC_BLE_PAIR_LIB_DEBUG_COLOR 0 +#endif + +// + +// NFC_BLE_PAIR_LIB_SECURITY_PARAMETERS - Common Peer Manager security parameters. + +//========================================================== +// BLE_NFC_SEC_PARAM_BOND - Enables device bonding. + +// If bonding is enabled at least one of the BLE_NFC_SEC_PARAM_KDIST options must be enabled. +//========================================================== +#ifndef BLE_NFC_SEC_PARAM_BOND +#define BLE_NFC_SEC_PARAM_BOND 1 +#endif +// BLE_NFC_SEC_PARAM_KDIST_OWN_ENC - Enables Long Term Key and Master Identification distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ENC +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_OWN_ID - Enables Identity Resolving Key and Identity Address Information distribution by device. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_OWN_ID +#define BLE_NFC_SEC_PARAM_KDIST_OWN_ID 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ENC - Enables Long Term Key and Master Identification distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ENC +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ENC 1 +#endif + +// BLE_NFC_SEC_PARAM_KDIST_PEER_ID - Enables Identity Resolving Key and Identity Address Information distribution by peer. + + +#ifndef BLE_NFC_SEC_PARAM_KDIST_PEER_ID +#define BLE_NFC_SEC_PARAM_KDIST_PEER_ID 1 +#endif + +// + +// BLE_NFC_SEC_PARAM_MIN_KEY_SIZE - Minimal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MIN_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MIN_KEY_SIZE 7 +#endif + +// BLE_NFC_SEC_PARAM_MAX_KEY_SIZE - Maximal size of a security key. + +// <7=> 7 +// <8=> 8 +// <9=> 9 +// <10=> 10 +// <11=> 11 +// <12=> 12 +// <13=> 13 +// <14=> 14 +// <15=> 15 +// <16=> 16 + +#ifndef BLE_NFC_SEC_PARAM_MAX_KEY_SIZE +#define BLE_NFC_SEC_PARAM_MAX_KEY_SIZE 16 +#endif + +// +//========================================================== + +// + +// NFC_BLE_PAIR_MSG_ENABLED - nfc_ble_pair_msg - NDEF message for OOB pairing encoder + + +#ifndef NFC_BLE_PAIR_MSG_ENABLED +#define NFC_BLE_PAIR_MSG_ENABLED 0 +#endif + +// NFC_CH_COMMON_ENABLED - nfc_ble_pair_common - OOB pairing common data + + +#ifndef NFC_CH_COMMON_ENABLED +#define NFC_CH_COMMON_ENABLED 0 +#endif + +// NFC_EP_OOB_REC_ENABLED - nfc_ep_oob_rec - EP record for BLE pairing encoder + + +#ifndef NFC_EP_OOB_REC_ENABLED +#define NFC_EP_OOB_REC_ENABLED 0 +#endif + +// NFC_HS_REC_ENABLED - nfc_hs_rec - Handover Select NDEF record encoder + + +#ifndef NFC_HS_REC_ENABLED +#define NFC_HS_REC_ENABLED 0 +#endif + +// NFC_LE_OOB_REC_ENABLED - nfc_le_oob_rec - LE record for BLE pairing encoder + + +#ifndef NFC_LE_OOB_REC_ENABLED +#define NFC_LE_OOB_REC_ENABLED 0 +#endif + +// NFC_LE_OOB_REC_PARSER_ENABLED - nfc_le_oob_rec_parser - LE record parser + + +#ifndef NFC_LE_OOB_REC_PARSER_ENABLED +#define NFC_LE_OOB_REC_PARSER_ENABLED 0 +#endif + +// NFC_NDEF_LAUNCHAPP_MSG_ENABLED - nfc_launchapp_msg - Encoding data for NDEF Application Launching message for NFC Tag + + +#ifndef NFC_NDEF_LAUNCHAPP_MSG_ENABLED +#define NFC_NDEF_LAUNCHAPP_MSG_ENABLED 0 +#endif + +// NFC_NDEF_LAUNCHAPP_REC_ENABLED - nfc_launchapp_rec - Encoding data for NDEF Application Launching record for NFC Tag + + +#ifndef NFC_NDEF_LAUNCHAPP_REC_ENABLED +#define NFC_NDEF_LAUNCHAPP_REC_ENABLED 0 +#endif + +// NFC_NDEF_MSG_ENABLED - nfc_ndef_msg - NFC NDEF Message generator module +//========================================================== +#ifndef NFC_NDEF_MSG_ENABLED +#define NFC_NDEF_MSG_ENABLED 0 +#endif +// NFC_NDEF_MSG_TAG_TYPE - NFC Tag Type + +// <2=> Type 2 Tag +// <4=> Type 4 Tag + +#ifndef NFC_NDEF_MSG_TAG_TYPE +#define NFC_NDEF_MSG_TAG_TYPE 2 +#endif + +// + +// NFC_NDEF_MSG_PARSER_ENABLED - nfc_ndef_msg_parser - NFC NDEF message parser module +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_ENABLED +#define NFC_NDEF_MSG_PARSER_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_MSG_PARSER_LOG_ENABLED +#define NFC_NDEF_MSG_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_MSG_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_MSG_PARSER_LOG_LEVEL +#define NFC_NDEF_MSG_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_MSG_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_MSG_PARSER_INFO_COLOR +#define NFC_NDEF_MSG_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_NDEF_RECORD_ENABLED - nfc_ndef_record - NFC NDEF Record generator module + + +#ifndef NFC_NDEF_RECORD_ENABLED +#define NFC_NDEF_RECORD_ENABLED 0 +#endif + +// NFC_NDEF_RECORD_PARSER_ENABLED - nfc_ndef_record_parser - NFC NDEF Record parser module +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_ENABLED +#define NFC_NDEF_RECORD_PARSER_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_NDEF_RECORD_PARSER_LOG_ENABLED +#define NFC_NDEF_RECORD_PARSER_LOG_ENABLED 0 +#endif +// NFC_NDEF_RECORD_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_NDEF_RECORD_PARSER_LOG_LEVEL +#define NFC_NDEF_RECORD_PARSER_LOG_LEVEL 3 +#endif + +// NFC_NDEF_RECORD_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_NDEF_RECORD_PARSER_INFO_COLOR +#define NFC_NDEF_RECORD_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_NDEF_TEXT_RECORD_ENABLED - nfc_text_rec - Encoding data for a text record for NFC Tag + + +#ifndef NFC_NDEF_TEXT_RECORD_ENABLED +#define NFC_NDEF_TEXT_RECORD_ENABLED 0 +#endif + +// NFC_NDEF_URI_MSG_ENABLED - nfc_uri_msg - Encoding data for NDEF message with URI record for NFC Tag + + +#ifndef NFC_NDEF_URI_MSG_ENABLED +#define NFC_NDEF_URI_MSG_ENABLED 0 +#endif + +// NFC_NDEF_URI_REC_ENABLED - nfc_uri_rec - Encoding data for a URI record for NFC Tag + + +#ifndef NFC_NDEF_URI_REC_ENABLED +#define NFC_NDEF_URI_REC_ENABLED 0 +#endif + +// NFC_PLATFORM_ENABLED - nfc_platform - NFC platform module for Clock control. +//========================================================== +#ifndef NFC_PLATFORM_ENABLED +#define NFC_PLATFORM_ENABLED 0 +#endif +// NFC_PLATFORM_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_PLATFORM_LOG_ENABLED +#define NFC_PLATFORM_LOG_ENABLED 0 +#endif +// NFC_PLATFORM_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_PLATFORM_LOG_LEVEL +#define NFC_PLATFORM_LOG_LEVEL 3 +#endif + +// NFC_PLATFORM_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_PLATFORM_INFO_COLOR +#define NFC_PLATFORM_INFO_COLOR 0 +#endif + +// NFC_PLATFORM_DEBUG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_PLATFORM_DEBUG_COLOR +#define NFC_PLATFORM_DEBUG_COLOR 0 +#endif + +// + +// + +// NFC_T2T_PARSER_ENABLED - nfc_type_2_tag_parser - Parser for decoding Type 2 Tag data +//========================================================== +#ifndef NFC_T2T_PARSER_ENABLED +#define NFC_T2T_PARSER_ENABLED 0 +#endif +// NFC_T2T_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_T2T_PARSER_LOG_ENABLED +#define NFC_T2T_PARSER_LOG_ENABLED 0 +#endif +// NFC_T2T_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_T2T_PARSER_LOG_LEVEL +#define NFC_T2T_PARSER_LOG_LEVEL 3 +#endif + +// NFC_T2T_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_T2T_PARSER_INFO_COLOR +#define NFC_T2T_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_T4T_APDU_ENABLED - nfc_t4t_apdu - APDU encoder/decoder for Type 4 Tag +//========================================================== +#ifndef NFC_T4T_APDU_ENABLED +#define NFC_T4T_APDU_ENABLED 0 +#endif +// NFC_T4T_APDU_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_T4T_APDU_LOG_ENABLED +#define NFC_T4T_APDU_LOG_ENABLED 0 +#endif +// NFC_T4T_APDU_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_T4T_APDU_LOG_LEVEL +#define NFC_T4T_APDU_LOG_LEVEL 3 +#endif + +// NFC_T4T_APDU_LOG_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_T4T_APDU_LOG_COLOR +#define NFC_T4T_APDU_LOG_COLOR 0 +#endif + +// + +// + +// NFC_T4T_CC_FILE_PARSER_ENABLED - nfc_t4t_cc_file - Capability Container file for Type 4 Tag +//========================================================== +#ifndef NFC_T4T_CC_FILE_PARSER_ENABLED +#define NFC_T4T_CC_FILE_PARSER_ENABLED 0 +#endif +// NFC_T4T_CC_FILE_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_T4T_CC_FILE_PARSER_LOG_ENABLED +#define NFC_T4T_CC_FILE_PARSER_LOG_ENABLED 0 +#endif +// NFC_T4T_CC_FILE_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_T4T_CC_FILE_PARSER_LOG_LEVEL +#define NFC_T4T_CC_FILE_PARSER_LOG_LEVEL 3 +#endif + +// NFC_T4T_CC_FILE_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_T4T_CC_FILE_PARSER_INFO_COLOR +#define NFC_T4T_CC_FILE_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED - nfc_t4t_hl_detection_procedures - NDEF Detection Procedure for Type 4 Tag +//========================================================== +#ifndef NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED +#define NFC_T4T_HL_DETECTION_PROCEDURES_ENABLED 0 +#endif +// NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED +#define NFC_T4T_HL_DETECTION_PROCEDURES_LOG_ENABLED 0 +#endif +// NFC_T4T_HL_DETECTION_PROCEDURES_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_T4T_HL_DETECTION_PROCEDURES_LOG_LEVEL +#define NFC_T4T_HL_DETECTION_PROCEDURES_LOG_LEVEL 3 +#endif + +// NFC_T4T_HL_DETECTION_PROCEDURES_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_T4T_HL_DETECTION_PROCEDURES_INFO_COLOR +#define NFC_T4T_HL_DETECTION_PROCEDURES_INFO_COLOR 0 +#endif + +// + +// APDU_BUFF_SIZE - Size (in bytes) of the buffer for APDU storage +#ifndef APDU_BUFF_SIZE +#define APDU_BUFF_SIZE 250 +#endif + +// CC_STORAGE_BUFF_SIZE - Size (in bytes) of the buffer for CC file storage +#ifndef CC_STORAGE_BUFF_SIZE +#define CC_STORAGE_BUFF_SIZE 64 +#endif + +// + +// NFC_T4T_TLV_BLOCK_PARSER_ENABLED - nfc_t4t_tlv_block - TLV block for Type 4 Tag +//========================================================== +#ifndef NFC_T4T_TLV_BLOCK_PARSER_ENABLED +#define NFC_T4T_TLV_BLOCK_PARSER_ENABLED 0 +#endif +// NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED - Enables logging in the module. +//========================================================== +#ifndef NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED +#define NFC_T4T_TLV_BLOCK_PARSER_LOG_ENABLED 0 +#endif +// NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL - Default Severity level + +// <0=> Off +// <1=> Error +// <2=> Warning +// <3=> Info +// <4=> Debug + +#ifndef NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL +#define NFC_T4T_TLV_BLOCK_PARSER_LOG_LEVEL 3 +#endif + +// NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR - ANSI escape code prefix. + +// <0=> Default +// <1=> Black +// <2=> Red +// <3=> Green +// <4=> Yellow +// <5=> Blue +// <6=> Magenta +// <7=> Cyan +// <8=> White + +#ifndef NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR +#define NFC_T4T_TLV_BLOCK_PARSER_INFO_COLOR 0 +#endif + +// + +// + +// +//========================================================== + +// nRF_Segger_RTT + +//========================================================== +// segger_rtt - SEGGER RTT + +//========================================================== +// SEGGER_RTT_CONFIG_BUFFER_SIZE_UP - Size of upstream buffer. +// Note that either @ref NRF_LOG_BACKEND_RTT_OUTPUT_BUFFER_SIZE +// or this value is actually used. It depends on which one is bigger. + +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_UP +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_UP 512 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS - Maximum number of upstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN - Size of downstream buffer. +#ifndef SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN +#define SEGGER_RTT_CONFIG_BUFFER_SIZE_DOWN 16 +#endif + +// SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS - Maximum number of downstream buffers. +#ifndef SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS +#define SEGGER_RTT_CONFIG_MAX_NUM_DOWN_BUFFERS 2 +#endif + +// SEGGER_RTT_CONFIG_DEFAULT_MODE - RTT behavior if the buffer is full. + + +// The following modes are supported: +// - SKIP - Do not block, output nothing. +// - TRIM - Do not block, output as much as fits. +// - BLOCK - Wait until there is space in the buffer. +// <0=> SKIP +// <1=> TRIM +// <2=> BLOCK_IF_FIFO_FULL + +#ifndef SEGGER_RTT_CONFIG_DEFAULT_MODE +#define SEGGER_RTT_CONFIG_DEFAULT_MODE 0 +#endif + +// +//========================================================== + +// +//========================================================== + +// nRF_SoftDevice + +//========================================================== +// NRF_SDH_BLE_ENABLED - nrf_sdh_ble - SoftDevice BLE event handler +//========================================================== +#ifndef NRF_SDH_BLE_ENABLED +#define NRF_SDH_BLE_ENABLED 1 +#endif +// BLE Stack configuration - Stack configuration parameters + +// The SoftDevice handler will configure the stack with these parameters when calling @ref nrf_sdh_ble_default_cfg_set. +// Other libraries might depend on these values; keep them up-to-date even if you are not explicitely calling @ref nrf_sdh_ble_default_cfg_set. +//========================================================== +// NRF_SDH_BLE_GAP_DATA_LENGTH <27-251> + + +// Requested BLE GAP data length to be negotiated. + +#ifndef NRF_SDH_BLE_GAP_DATA_LENGTH +#define NRF_SDH_BLE_GAP_DATA_LENGTH 251 +#endif + +// NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - Maximum number of peripheral links. +#ifndef NRF_SDH_BLE_PERIPHERAL_LINK_COUNT +#define NRF_SDH_BLE_PERIPHERAL_LINK_COUNT 1 +#endif + +// NRF_SDH_BLE_CENTRAL_LINK_COUNT - Maximum number of central links. +#ifndef NRF_SDH_BLE_CENTRAL_LINK_COUNT +#define NRF_SDH_BLE_CENTRAL_LINK_COUNT 0 +#endif + +// NRF_SDH_BLE_TOTAL_LINK_COUNT - Total link count. +// Maximum number of total concurrent connections using the default configuration. + +#ifndef NRF_SDH_BLE_TOTAL_LINK_COUNT +#define NRF_SDH_BLE_TOTAL_LINK_COUNT 1 +#endif + +// NRF_SDH_BLE_GAP_EVENT_LENGTH - GAP event length. +// The time set aside for this connection on every connection interval in 1.25 ms units. + +#ifndef NRF_SDH_BLE_GAP_EVENT_LENGTH +#define NRF_SDH_BLE_GAP_EVENT_LENGTH 6 +#endif + +// NRF_SDH_BLE_GATT_MAX_MTU_SIZE - Static maximum MTU size. +#ifndef NRF_SDH_BLE_GATT_MAX_MTU_SIZE +#define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247 +#endif + +// NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE - Attribute Table size in bytes. The size must be a multiple of 4. +#ifndef NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE +#define NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE 1408 +#endif + +// NRF_SDH_BLE_VS_UUID_COUNT - The number of vendor-specific UUIDs. +#ifndef NRF_SDH_BLE_VS_UUID_COUNT +#define NRF_SDH_BLE_VS_UUID_COUNT 1 +#endif + +// NRF_SDH_BLE_SERVICE_CHANGED - Include the Service Changed characteristic in the Attribute Table. + + +#ifndef NRF_SDH_BLE_SERVICE_CHANGED +#define NRF_SDH_BLE_SERVICE_CHANGED 0 +#endif + +// +//========================================================== + +// BLE Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_BLE_OBSERVER_PRIO_LEVELS - Total number of priority levels for BLE observers. +// This setting configures the number of priority levels available for BLE event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_BLE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_BLE_OBSERVER_PRIO_LEVELS 4 +#endif + +// BLE Observers priorities - Invididual priorities + +//========================================================== +// BLE_ADV_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Advertising module. + +#ifndef BLE_ADV_BLE_OBSERVER_PRIO +#define BLE_ADV_BLE_OBSERVER_PRIO 1 +#endif + +// BLE_ANCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Apple Notification Service Client. + +#ifndef BLE_ANCS_C_BLE_OBSERVER_PRIO +#define BLE_ANCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_ANS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Alert Notification Service Client. + +#ifndef BLE_ANS_C_BLE_OBSERVER_PRIO +#define BLE_ANS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service. + +#ifndef BLE_BAS_BLE_OBSERVER_PRIO +#define BLE_BAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Battery Service Client. + +#ifndef BLE_BAS_C_BLE_OBSERVER_PRIO +#define BLE_BAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_BPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Blood Pressure Service. + +#ifndef BLE_BPS_BLE_OBSERVER_PRIO +#define BLE_BPS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection parameters module. + +#ifndef BLE_CONN_PARAMS_BLE_OBSERVER_PRIO +#define BLE_CONN_PARAMS_BLE_OBSERVER_PRIO 1 +#endif + +// BLE_CONN_STATE_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Connection State module. + +#ifndef BLE_CONN_STATE_BLE_OBSERVER_PRIO +#define BLE_CONN_STATE_BLE_OBSERVER_PRIO 0 +#endif + +// BLE_CSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Cycling Speed and Cadence Service. + +#ifndef BLE_CSCS_BLE_OBSERVER_PRIO +#define BLE_CSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_CTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Current Time Service Client. + +#ifndef BLE_CTS_C_BLE_OBSERVER_PRIO +#define BLE_CTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_DB_DISC_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Database Discovery module. + +#ifndef BLE_DB_DISC_BLE_OBSERVER_PRIO +#define BLE_DB_DISC_BLE_OBSERVER_PRIO 1 +#endif + +// BLE_DFU_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_BLE_OBSERVER_PRIO +#define BLE_DFU_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_DIS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Device Information Client. + +#ifndef BLE_DIS_C_BLE_OBSERVER_PRIO +#define BLE_DIS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_GLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Glucose Service. + +#ifndef BLE_GLS_BLE_OBSERVER_PRIO +#define BLE_GLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HIDS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Human Interface Device Service. + +#ifndef BLE_HIDS_BLE_OBSERVER_PRIO +#define BLE_HIDS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service. + +#ifndef BLE_HRS_BLE_OBSERVER_PRIO +#define BLE_HRS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HRS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Heart Rate Service Client. + +#ifndef BLE_HRS_C_BLE_OBSERVER_PRIO +#define BLE_HRS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_HTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Health Thermometer Service. + +#ifndef BLE_HTS_BLE_OBSERVER_PRIO +#define BLE_HTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service. + +#ifndef BLE_IAS_BLE_OBSERVER_PRIO +#define BLE_IAS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_IAS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Immediate Alert Service Client. + +#ifndef BLE_IAS_C_BLE_OBSERVER_PRIO +#define BLE_IAS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service. + +#ifndef BLE_LBS_BLE_OBSERVER_PRIO +#define BLE_LBS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LBS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the LED Button Service Client. + +#ifndef BLE_LBS_C_BLE_OBSERVER_PRIO +#define BLE_LBS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LLS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Link Loss Service. + +#ifndef BLE_LLS_BLE_OBSERVER_PRIO +#define BLE_LLS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_LNS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Location Navigation Service. + +#ifndef BLE_LNS_BLE_OBSERVER_PRIO +#define BLE_LNS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Service. + +#ifndef BLE_NUS_BLE_OBSERVER_PRIO +#define BLE_NUS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_NUS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the UART Central Service. + +#ifndef BLE_NUS_C_BLE_OBSERVER_PRIO +#define BLE_NUS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service. + +#ifndef BLE_OTS_BLE_OBSERVER_PRIO +#define BLE_OTS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_OTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Object transfer service client. + +#ifndef BLE_OTS_C_BLE_OBSERVER_PRIO +#define BLE_OTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Service. + +#ifndef BLE_RSCS_BLE_OBSERVER_PRIO +#define BLE_RSCS_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_RSCS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Running Speed and Cadence Client. + +#ifndef BLE_RSCS_C_BLE_OBSERVER_PRIO +#define BLE_RSCS_C_BLE_OBSERVER_PRIO 2 +#endif + +// BLE_TPS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the TX Power Service. + +#ifndef BLE_TPS_BLE_OBSERVER_PRIO +#define BLE_TPS_BLE_OBSERVER_PRIO 2 +#endif + +// BSP_BTN_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Button Control module. + +#ifndef BSP_BTN_BLE_OBSERVER_PRIO +#define BSP_BTN_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the NFC pairing library. + +#ifndef NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO +#define NFC_BLE_PAIR_LIB_BLE_OBSERVER_PRIO 1 +#endif + +// NRF_BLE_BMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Bond Management Service. + +#ifndef NRF_BLE_BMS_BLE_OBSERVER_PRIO +#define NRF_BLE_BMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_CGMS_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Contiuon Glucose Monitoring Service. + +#ifndef NRF_BLE_CGMS_BLE_OBSERVER_PRIO +#define NRF_BLE_CGMS_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_ES_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Eddystone module. + +#ifndef NRF_BLE_ES_BLE_OBSERVER_PRIO +#define NRF_BLE_ES_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT Service Client. + +#ifndef NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO +#define NRF_BLE_GATTS_C_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_GATT_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT module. + +#ifndef NRF_BLE_GATT_BLE_OBSERVER_PRIO +#define NRF_BLE_GATT_BLE_OBSERVER_PRIO 1 +#endif + +// NRF_BLE_GQ_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the GATT Queue module. + +#ifndef NRF_BLE_GQ_BLE_OBSERVER_PRIO +#define NRF_BLE_GQ_BLE_OBSERVER_PRIO 1 +#endif + +// NRF_BLE_QWR_BLE_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the Queued writes module. + +#ifndef NRF_BLE_QWR_BLE_OBSERVER_PRIO +#define NRF_BLE_QWR_BLE_OBSERVER_PRIO 2 +#endif + +// NRF_BLE_SCAN_OBSERVER_PRIO +// Priority for dispatching the BLE events to the Scanning Module. + +#ifndef NRF_BLE_SCAN_OBSERVER_PRIO +#define NRF_BLE_SCAN_OBSERVER_PRIO 1 +#endif + +// PM_BLE_OBSERVER_PRIO - Priority with which BLE events are dispatched to the Peer Manager module. +#ifndef PM_BLE_OBSERVER_PRIO +#define PM_BLE_OBSERVER_PRIO 1 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_ENABLED - nrf_sdh - SoftDevice handler +//========================================================== +#ifndef NRF_SDH_ENABLED +#define NRF_SDH_ENABLED 1 +#endif +// Dispatch model + +// This setting configures how Stack events are dispatched to the application. +//========================================================== +// NRF_SDH_DISPATCH_MODEL + + +// NRF_SDH_DISPATCH_MODEL_INTERRUPT: SoftDevice events are passed to the application from the interrupt context. +// NRF_SDH_DISPATCH_MODEL_APPSH: SoftDevice events are scheduled using @ref app_scheduler. +// NRF_SDH_DISPATCH_MODEL_POLLING: SoftDevice events are to be fetched manually. +// <0=> NRF_SDH_DISPATCH_MODEL_INTERRUPT +// <1=> NRF_SDH_DISPATCH_MODEL_APPSH +// <2=> NRF_SDH_DISPATCH_MODEL_POLLING + +#ifndef NRF_SDH_DISPATCH_MODEL +#define NRF_SDH_DISPATCH_MODEL 1 +#endif + +// +//========================================================== + +// Clock - SoftDevice clock configuration + +//========================================================== +// NRF_SDH_CLOCK_LF_SRC - SoftDevice clock source. + +// <0=> NRF_CLOCK_LF_SRC_RC +// <1=> NRF_CLOCK_LF_SRC_XTAL +// <2=> NRF_CLOCK_LF_SRC_SYNTH + +#ifndef NRF_SDH_CLOCK_LF_SRC +#define NRF_SDH_CLOCK_LF_SRC 1 +#endif + +// NRF_SDH_CLOCK_LF_RC_CTIV - SoftDevice calibration timer interval. +#ifndef NRF_SDH_CLOCK_LF_RC_CTIV +#define NRF_SDH_CLOCK_LF_RC_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_RC_TEMP_CTIV - SoftDevice calibration timer interval under constant temperature. +// How often (in number of calibration intervals) the RC oscillator shall be calibrated +// if the temperature has not changed. + +#ifndef NRF_SDH_CLOCK_LF_RC_TEMP_CTIV +#define NRF_SDH_CLOCK_LF_RC_TEMP_CTIV 0 +#endif + +// NRF_SDH_CLOCK_LF_ACCURACY - External clock accuracy used in the LL to compute timing. + +// <0=> NRF_CLOCK_LF_ACCURACY_250_PPM +// <1=> NRF_CLOCK_LF_ACCURACY_500_PPM +// <2=> NRF_CLOCK_LF_ACCURACY_150_PPM +// <3=> NRF_CLOCK_LF_ACCURACY_100_PPM +// <4=> NRF_CLOCK_LF_ACCURACY_75_PPM +// <5=> NRF_CLOCK_LF_ACCURACY_50_PPM +// <6=> NRF_CLOCK_LF_ACCURACY_30_PPM +// <7=> NRF_CLOCK_LF_ACCURACY_20_PPM +// <8=> NRF_CLOCK_LF_ACCURACY_10_PPM +// <9=> NRF_CLOCK_LF_ACCURACY_5_PPM +// <10=> NRF_CLOCK_LF_ACCURACY_2_PPM +// <11=> NRF_CLOCK_LF_ACCURACY_1_PPM + +#ifndef NRF_SDH_CLOCK_LF_ACCURACY +#define NRF_SDH_CLOCK_LF_ACCURACY 7 +#endif + +// +//========================================================== + +// SDH Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_REQ_OBSERVER_PRIO_LEVELS - Total number of priority levels for request observers. +// This setting configures the number of priority levels available for the SoftDevice request event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_REQ_OBSERVER_PRIO_LEVELS +#define NRF_SDH_REQ_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STATE_OBSERVER_PRIO_LEVELS - Total number of priority levels for state observers. +// This setting configures the number of priority levels available for the SoftDevice state event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STATE_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STATE_OBSERVER_PRIO_LEVELS 2 +#endif + +// NRF_SDH_STACK_OBSERVER_PRIO_LEVELS - Total number of priority levels for stack event observers. +// This setting configures the number of priority levels available for the SoftDevice stack event handlers (ANT, BLE, SoC). +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_STACK_OBSERVER_PRIO_LEVELS +#define NRF_SDH_STACK_OBSERVER_PRIO_LEVELS 2 +#endif + + +// State Observers priorities - Invididual priorities + +//========================================================== +// CLOCK_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_STATE_OBSERVER_PRIO +#define CLOCK_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_STATE_OBSERVER_PRIO +#define POWER_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// RNG_CONFIG_STATE_OBSERVER_PRIO +// Priority with which state events are dispatched to this module. + +#ifndef RNG_CONFIG_STATE_OBSERVER_PRIO +#define RNG_CONFIG_STATE_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// Stack Event Observers priorities - Invididual priorities + +//========================================================== +// NRF_SDH_ANT_STACK_OBSERVER_PRIO +// This setting configures the priority with which ANT events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have ANT events dispatched before or after other stack events, such as BLE or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_ANT_STACK_OBSERVER_PRIO +#define NRF_SDH_ANT_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_BLE_STACK_OBSERVER_PRIO +// This setting configures the priority with which BLE events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have BLE events dispatched before or after other stack events, such as ANT or SoC. +// Zero is the highest priority. + +#ifndef NRF_SDH_BLE_STACK_OBSERVER_PRIO +#define NRF_SDH_BLE_STACK_OBSERVER_PRIO 0 +#endif + +// NRF_SDH_SOC_STACK_OBSERVER_PRIO +// This setting configures the priority with which SoC events are processed with respect to other events coming from the stack. +// Modify this setting if you need to have SoC events dispatched before or after other stack events, such as ANT or BLE. +// Zero is the highest priority. + +#ifndef NRF_SDH_SOC_STACK_OBSERVER_PRIO +#define NRF_SDH_SOC_STACK_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// NRF_SDH_SOC_ENABLED - nrf_sdh_soc - SoftDevice SoC event handler +//========================================================== +#ifndef NRF_SDH_SOC_ENABLED +#define NRF_SDH_SOC_ENABLED 1 +#endif +// SoC Observers - Observers and priority levels + +//========================================================== +// NRF_SDH_SOC_OBSERVER_PRIO_LEVELS - Total number of priority levels for SoC observers. +// This setting configures the number of priority levels available for the SoC event handlers. +// The priority level of a handler determines the order in which it receives events, with respect to other handlers. + +#ifndef NRF_SDH_SOC_OBSERVER_PRIO_LEVELS +#define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS 2 +#endif + +// SoC Observers priorities - Invididual priorities + +//========================================================== +// BLE_DFU_SOC_OBSERVER_PRIO +// Priority with which BLE events are dispatched to the DFU Service. + +#ifndef BLE_DFU_SOC_OBSERVER_PRIO +#define BLE_DFU_SOC_OBSERVER_PRIO 1 +#endif + +// CLOCK_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Clock driver. + +#ifndef CLOCK_CONFIG_SOC_OBSERVER_PRIO +#define CLOCK_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// POWER_CONFIG_SOC_OBSERVER_PRIO +// Priority with which SoC events are dispatched to the Power driver. + +#ifndef POWER_CONFIG_SOC_OBSERVER_PRIO +#define POWER_CONFIG_SOC_OBSERVER_PRIO 0 +#endif + +// +//========================================================== + +// +//========================================================== + + +// + +// +//========================================================== + +// <<< end of configuration section >>> +#endif //SDK_CONFIG_H + diff --git a/core/embed/ble_firmware/uecc/.gitignore b/core/embed/ble_firmware/uecc/.gitignore new file mode 100644 index 000000000..561bd57ec --- /dev/null +++ b/core/embed/ble_firmware/uecc/.gitignore @@ -0,0 +1,11 @@ +__build__/ +__pycache__ +*.pyc +*.pyo +*.pyd +*.pyz +*.egg-info/ +*.a +*.o +*.so +.DS_Store diff --git a/core/embed/ble_firmware/uecc/LICENSE.txt b/core/embed/ble_firmware/uecc/LICENSE.txt new file mode 100644 index 000000000..ab099ae5a --- /dev/null +++ b/core/embed/ble_firmware/uecc/LICENSE.txt @@ -0,0 +1,21 @@ +Copyright (c) 2014, Kenneth MacKay +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/core/embed/ble_firmware/uecc/README.md b/core/embed/ble_firmware/uecc/README.md new file mode 100644 index 000000000..111321bf7 --- /dev/null +++ b/core/embed/ble_firmware/uecc/README.md @@ -0,0 +1,41 @@ +micro-ecc +========== + +A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors. + +The static version of micro-ecc (ie, where the curve was selected at compile-time) can be found in the "static" branch. + +Features +-------- + + * Resistant to known side-channel attacks. + * Written in C, with optional GCC inline assembly for AVR, ARM and Thumb platforms. + * Supports 8, 32, and 64-bit architectures. + * Small code size. + * No dynamic memory allocation. + * Support for 5 standard curves: secp160r1, secp192r1, secp224r1, secp256r1, and secp256k1. + * BSD 2-clause license. + +Usage Notes +----------- +### Point Representation ### +Compressed points are represented in the standard format as defined in http://www.secg.org/sec1-v2.pdf; uncompressed points are represented in standard format, but without the `0x04` prefix. All functions except `uECC_decompress()` only accept uncompressed points; use `uECC_compress()` and `uECC_decompress()` to convert between compressed and uncompressed point representations. + +Private keys are represented in the standard format. + +### Using the Code ### + +I recommend just copying (or symlink) the uECC files into your project. Then just `#include "uECC.h"` to use the micro-ecc functions. + +For use with Arduino, you can use the Library Manager to download micro-ecc (**Sketch**=>**Include Library**=>**Manage Libraries**). You can then use uECC just like any other Arduino library (uECC should show up in the **Sketch**=>**Import Library** submenu). + +See uECC.h for documentation for each function. + +### Compilation Notes ### + + * Should compile with any C/C++ compiler that supports stdint.h (this includes Visual Studio 2013). + * If you want to change the defaults for any of the uECC compile-time options (such as `uECC_OPTIMIZATION_LEVEL`), you must change them in your Makefile or similar so that uECC.c is compiled with the desired values (ie, compile uECC.c with `-DuECC_OPTIMIZATION_LEVEL=3` or whatever). + * When compiling for a Thumb-1 platform, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher). + * When compiling for an ARM/Thumb-2 platform with `uECC_OPTIMIZATION_LEVEL` >= 3, you must use the `-fomit-frame-pointer` GCC option (this is enabled by default when compiling with `-O1` or higher). + * When compiling for AVR, you must have optimizations enabled (compile with `-O1` or higher). + * When building for Windows, you will need to link in the `advapi32.lib` system library. diff --git a/core/embed/ble_firmware/uecc/asm_arm.inc b/core/embed/ble_firmware/uecc/asm_arm.inc new file mode 100644 index 000000000..12e747f9b --- /dev/null +++ b/core/embed/ble_firmware/uecc/asm_arm.inc @@ -0,0 +1,820 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_H_ +#define _UECC_ASM_ARM_H_ + +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #define uECC_MIN_WORDS 8 +#endif +#if uECC_SUPPORTS_secp224r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 7 +#endif +#if uECC_SUPPORTS_secp192r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 6 +#endif +#if uECC_SUPPORTS_secp160r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 5 +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb) + #define REG_RW "+&l" + #define REG_WRITE "=&l" +#else + #define REG_RW "+&r" + #define REG_WRITE "=&r" +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb || uECC_PLATFORM == uECC_arm_thumb2) + #define REG_RW_LO "+&l" + #define REG_WRITE_LO "=&l" +#else + #define REG_RW_LO "+&r" + #define REG_WRITE_LO "=&r" +#endif + +#if (uECC_PLATFORM == uECC_arm_thumb2) + #define RESUME_SYNTAX +#else + #define RESUME_SYNTAX ".syntax divided \n\t" +#endif + +#if (uECC_OPTIMIZATION_LEVEL >= 2) + +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_MAX_WORDS != uECC_MIN_WORDS) + #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2) + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1; + #else /* ARM */ + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4; + #endif +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "movs %[carry], #0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "adr %[left], 1f \n\t" + ".align 4 \n\t" + "adds %[jump], %[left] \n\t" + #endif + + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "adds %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t" + + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "bx %[jump] \n\t" + #endif + "1: \n\t" + REPEAT(DEC(uECC_MAX_WORDS), + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "adcs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t") + + "adcs %[carry], %[carry] \n\t" + RESUME_SYNTAX + : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right), + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + [jump] REG_RW_LO (jump), + #endif + [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word), + [right] REG_WRITE_LO (right_word) + : + : "cc", "memory" + ); + return carry; +} +#define asm_add 1 + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_MAX_WORDS != uECC_MIN_WORDS) + #if (uECC_PLATFORM == uECC_arm_thumb) || (uECC_PLATFORM == uECC_arm_thumb2) + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 2 + 1; + #else /* ARM */ + uint32_t jump = (uECC_MAX_WORDS - num_words) * 4 * 4; + #endif +#endif + uint32_t carry; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "movs %[carry], #0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "adr %[left], 1f \n\t" + ".align 4 \n\t" + "adds %[jump], %[left] \n\t" + #endif + + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "subs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t" + + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "bx %[jump] \n\t" + #endif + "1: \n\t" + REPEAT(DEC(uECC_MAX_WORDS), + "ldmia %[lptr]!, {%[left]} \n\t" + "ldmia %[rptr]!, {%[right]} \n\t" + "sbcs %[left], %[right] \n\t" + "stmia %[dptr]!, {%[left]} \n\t") + + "adcs %[carry], %[carry] \n\t" + RESUME_SYNTAX + : [dptr] REG_RW_LO (result), [lptr] REG_RW_LO (left), [rptr] REG_RW_LO (right), + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + [jump] REG_RW_LO (jump), + #endif + [carry] REG_WRITE_LO (carry), [left] REG_WRITE_LO (left_word), + [right] REG_WRITE_LO (right_word) + : + : "cc", "memory" + ); + return !carry; /* Note that on ARM, carry flag set means "no borrow" when subtracting + (for some reason...) */ +} +#define asm_sub 1 + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */ + +#if (uECC_OPTIMIZATION_LEVEL >= 3) + +#if (uECC_PLATFORM != uECC_arm_thumb) + +#if uECC_ARM_USE_UMAAL + #include "asm_arm_mult_square_umaal.inc" +#else + #include "asm_arm_mult_square.inc" +#endif + +#if (uECC_OPTIMIZATION_LEVEL == 3) + +uECC_VLI_API void uECC_vli_mult(uint32_t *result, + const uint32_t *left, + const uint32_t *right, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register const uint32_t *r2 __asm__("r2") = right; + register uint32_t r3 __asm__("r3") = num_words; + + __asm__ volatile ( + ".syntax unified \n\t" +#if (uECC_MIN_WORDS == 5) + FAST_MULT_ASM_5 + #if (uECC_MAX_WORDS > 5) + FAST_MULT_ASM_5_TO_6 + #endif + #if (uECC_MAX_WORDS > 6) + FAST_MULT_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 6) + FAST_MULT_ASM_6 + #if (uECC_MAX_WORDS > 6) + FAST_MULT_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 7) + FAST_MULT_ASM_7 + #if (uECC_MAX_WORDS > 7) + FAST_MULT_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 8) + FAST_MULT_ASM_8 +#endif + "1: \n\t" + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register uint32_t r2 __asm__("r2") = num_words; + + __asm__ volatile ( + ".syntax unified \n\t" +#if (uECC_MIN_WORDS == 5) + FAST_SQUARE_ASM_5 + #if (uECC_MAX_WORDS > 5) + FAST_SQUARE_ASM_5_TO_6 + #endif + #if (uECC_MAX_WORDS > 6) + FAST_SQUARE_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 6) + FAST_SQUARE_ASM_6 + #if (uECC_MAX_WORDS > 6) + FAST_SQUARE_ASM_6_TO_7 + #endif + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 7) + FAST_SQUARE_ASM_7 + #if (uECC_MAX_WORDS > 7) + FAST_SQUARE_ASM_7_TO_8 + #endif +#elif (uECC_MIN_WORDS == 8) + FAST_SQUARE_ASM_8 +#endif + + "1: \n\t" + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#else /* (uECC_OPTIMIZATION_LEVEL > 3) */ + +uECC_VLI_API void uECC_vli_mult(uint32_t *result, + const uint32_t *left, + const uint32_t *right, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register const uint32_t *r2 __asm__("r2") = right; + register uint32_t r3 __asm__("r3") = num_words; + +#if uECC_SUPPORTS_secp160r1 + if (num_words == 5) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_5 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp192r1 + if (num_words == 6) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_6 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp224r1 + if (num_words == 7) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_7 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + if (num_words == 8) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_MULT_ASM_8 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1), "+r" (r2) + : "r" (r3) + : "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + register uint32_t *r0 __asm__("r0") = result; + register const uint32_t *r1 __asm__("r1") = left; + register uint32_t r2 __asm__("r2") = num_words; + +#if uECC_SUPPORTS_secp160r1 + if (num_words == 5) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_5 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp192r1 + if (num_words == 6) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_6 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if uECC_SUPPORTS_secp224r1 + if (num_words == 7) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_7 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + if (num_words == 8) { + __asm__ volatile ( + ".syntax unified \n\t" + FAST_SQUARE_ASM_8 + RESUME_SYNTAX + : "+r" (r0), "+r" (r1) + : "r" (r2) + : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); + return; + } +#endif +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#endif /* (uECC_OPTIMIZATION_LEVEL > 3) */ + +#endif /* uECC_PLATFORM != uECC_arm_thumb */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */ + +/* ---- "Small" implementations ---- */ + +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uint32_t carry = 0; + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "1: \n\t" + "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */ + "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */ + "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */ + "adcs %[left], %[left], %[right] \n\t" /* Add with carry. */ + "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */ + "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */ + "subs %[ctr], #1 \n\t" /* Decrement counter. */ + "bne 1b \n\t" /* Loop until counter == 0. */ + RESUME_SYNTAX + : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right), + [ctr] REG_RW (num_words), [carry] REG_RW (carry), + [left] REG_WRITE (left_word), [right] REG_WRITE (right_word) + : + : "cc", "memory" + ); + return carry; +} +#define asm_add 1 +#endif + +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */ + uint32_t left_word; + uint32_t right_word; + + __asm__ volatile ( + ".syntax unified \n\t" + "1: \n\t" + "ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */ + "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */ + "lsrs %[carry], #1 \n\t" /* Set up carry flag (carry = 0 after this). */ + "sbcs %[left], %[left], %[right] \n\t" /* Subtract with borrow. */ + "adcs %[carry], %[carry], %[carry] \n\t" /* Store carry bit. */ + "stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */ + "subs %[ctr], #1 \n\t" /* Decrement counter. */ + "bne 1b \n\t" /* Loop until counter == 0. */ + RESUME_SYNTAX + : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right), + [ctr] REG_RW (num_words), [carry] REG_RW (carry), + [left] REG_WRITE (left_word), [right] REG_WRITE (right_word) + : + : "cc", "memory" + ); + return !carry; +} +#define asm_sub 1 +#endif + +#if !asm_mult +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { +#if (uECC_PLATFORM != uECC_arm_thumb) + uint32_t c0 = 0; + uint32_t c1 = 0; + uint32_t c2 = 0; + uint32_t k = 0; + uint32_t i; + uint32_t t0, t1; + + __asm__ volatile ( + ".syntax unified \n\t" + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[i], #0 \n\t" /* i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[i], %[k] \n\t" /* i = k */ + "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */ + + "ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = right[k - i] */ + "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */ + + "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */ + + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "adds %[i], #4 \n\t" /* i += 4 */ + "cmp %[i], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */ + "bgt 4f \n\t" /* if so, exit the loop */ + "cmp %[i], %[k] \n\t" /* i <= k? */ + "ble 3b \n\t" /* if so, continue looping */ + + "4: \n\t" /* end inner loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */ + "mov %[c0], %[c1] \n\t" /* c0 = c1 */ + "mov %[c1], %[c2] \n\t" /* c1 = c2 */ + "movs %[c2], #0 \n\t" /* c2 = 0 */ + "adds %[k], #4 \n\t" /* k += 4 */ + "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */ + RESUME_SYNTAX + : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), + [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1) + : [result] "r" (result), [left] "r" (left), [right] "r" (right), + [last_word] "r" ((num_words - 1) * 4) + : "cc", "memory" + ); + +#else /* Thumb-1 */ + uint32_t r4, r5, r6, r7; + + __asm__ volatile ( + ".syntax unified \n\t" + "subs %[r3], #1 \n\t" /* r3 = num_words - 1 */ + "lsls %[r3], #2 \n\t" /* r3 = (num_words - 1) * 4 */ + "mov r8, %[r3] \n\t" /* r8 = (num_words - 1) * 4 */ + "lsls %[r3], #1 \n\t" /* r3 = (num_words - 1) * 8 */ + "mov r9, %[r3] \n\t" /* r9 = (num_words - 1) * 8 */ + "movs %[r3], #0 \n\t" /* c0 = 0 */ + "movs %[r4], #0 \n\t" /* c1 = 0 */ + "movs %[r5], #0 \n\t" /* c2 = 0 */ + "movs %[r6], #0 \n\t" /* k = 0 */ + + "push {%[r0]} \n\t" /* keep result on the stack */ + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[r7], #0 \n\t" /* r7 = i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[r7], %[r6] \n\t" /* r7 = k */ + "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */ + "subs %[r7], %[r0] \n\t" /* r7 = i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "mov r10, %[r3] \n\t" + "mov r11, %[r4] \n\t" + "mov r12, %[r5] \n\t" + "mov r14, %[r6] \n\t" + "subs %[r0], %[r6], %[r7] \n\t" /* r0 = k - i */ + + "ldr %[r4], [%[r2], %[r0]] \n\t" /* r4 = right[k - i] */ + "ldr %[r0], [%[r1], %[r7]] \n\t" /* r0 = left[i] */ + + "lsrs %[r3], %[r0], #16 \n\t" /* r3 = a1 */ + "uxth %[r0], %[r0] \n\t" /* r0 = a0 */ + + "lsrs %[r5], %[r4], #16 \n\t" /* r5 = b1 */ + "uxth %[r4], %[r4] \n\t" /* r4 = b0 */ + + "movs %[r6], %[r3] \n\t" /* r6 = a1 */ + "muls %[r6], %[r5], %[r6] \n\t" /* r6 = a1 * b1 */ + "muls %[r3], %[r4], %[r3] \n\t" /* r3 = b0 * a1 */ + "muls %[r5], %[r0], %[r5] \n\t" /* r5 = a0 * b1 */ + "muls %[r0], %[r4], %[r0] \n\t" /* r0 = a0 * b0 */ + + /* Add middle terms */ + "lsls %[r4], %[r3], #16 \n\t" + "lsrs %[r3], %[r3], #16 \n\t" + "adds %[r0], %[r4] \n\t" + "adcs %[r6], %[r3] \n\t" + + "lsls %[r4], %[r5], #16 \n\t" + "lsrs %[r5], %[r5], #16 \n\t" + "adds %[r0], %[r4] \n\t" + "adcs %[r6], %[r5] \n\t" + + "mov %[r3], r10\n\t" + "mov %[r4], r11\n\t" + "mov %[r5], r12\n\t" + "adds %[r3], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r4], %[r6] \n\t" /* add high word to c1, including carry */ + "movs %[r0], #0 \n\t" /* r0 = 0 (does not affect carry bit) */ + "adcs %[r5], %[r0] \n\t" /* add carry to c2 */ + + "mov %[r6], r14\n\t" /* r6 = k */ + + "adds %[r7], #4 \n\t" /* i += 4 */ + "cmp %[r7], r8 \n\t" /* i > (num_words - 1) (times 4)? */ + "bgt 4f \n\t" /* if so, exit the loop */ + "cmp %[r7], %[r6] \n\t" /* i <= k? */ + "ble 3b \n\t" /* if so, continue looping */ + + "4: \n\t" /* end inner loop */ + + "ldr %[r0], [sp, #0] \n\t" /* r0 = result */ + + "str %[r3], [%[r0], %[r6]] \n\t" /* result[k] = c0 */ + "mov %[r3], %[r4] \n\t" /* c0 = c1 */ + "mov %[r4], %[r5] \n\t" /* c1 = c2 */ + "movs %[r5], #0 \n\t" /* c2 = 0 */ + "adds %[r6], #4 \n\t" /* k += 4 */ + "cmp %[r6], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[r6], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[r3], [%[r0], %[r6]] \n\t" /* result[num_words * 2 - 1] = c0 */ + "pop {%[r0]} \n\t" /* pop result off the stack */ + + RESUME_SYNTAX + : [r3] "+l" (num_words), [r4] "=&l" (r4), + [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) + : [r0] "l" (result), [r1] "l" (left), [r2] "l" (right) + : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +#endif +} +#define asm_mult 1 +#endif + +#if uECC_SQUARE_FUNC +#if !asm_square +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { +#if (uECC_PLATFORM != uECC_arm_thumb) + uint32_t c0 = 0; + uint32_t c1 = 0; + uint32_t c2 = 0; + uint32_t k = 0; + uint32_t i, tt; + uint32_t t0, t1; + + __asm__ volatile ( + ".syntax unified \n\t" + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[i], #0 \n\t" /* i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[i], %[k] \n\t" /* i = k */ + "subs %[i], %[last_word] \n\t" /* i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */ + + "ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = left[k - i] */ + "ldr %[t0], [%[left], %[i]] \n\t" /* t0 = left[i] */ + + "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * right[k - i] */ + + "cmp %[i], %[tt] \n\t" /* (i < k - i) ? */ + "bge 4f \n\t" /* if i >= k - i, skip */ + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "4: \n\t" + "adds %[c0], %[c0], %[t0] \n\t" /* add low word to c0 */ + "adcs %[c1], %[c1], %[t1] \n\t" /* add high word to c1, including carry */ + "adcs %[c2], %[c2], #0 \n\t" /* add carry to c2 */ + + "adds %[i], #4 \n\t" /* i += 4 */ + "cmp %[i], %[k] \n\t" /* i >= k? */ + "bge 5f \n\t" /* if so, exit the loop */ + "subs %[tt], %[k], %[i] \n\t" /* tt = k - i */ + "cmp %[i], %[tt] \n\t" /* i <= k - i? */ + "ble 3b \n\t" /* if so, continue looping */ + + "5: \n\t" /* end inner loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[k] = c0 */ + "mov %[c0], %[c1] \n\t" /* c0 = c1 */ + "mov %[c1], %[c2] \n\t" /* c1 = c2 */ + "movs %[c2], #0 \n\t" /* c2 = 0 */ + "adds %[k], #4 \n\t" /* k += 4 */ + "cmp %[k], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, start with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */ + RESUME_SYNTAX + : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), + [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1) + : [result] "r" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4) + : "cc", "memory" + ); + +#else + uint32_t r3, r4, r5, r6, r7; + + __asm__ volatile ( + ".syntax unified \n\t" + "subs %[r2], #1 \n\t" /* r2 = num_words - 1 */ + "lsls %[r2], #2 \n\t" /* r2 = (num_words - 1) * 4 */ + "mov r8, %[r2] \n\t" /* r8 = (num_words - 1) * 4 */ + "lsls %[r2], #1 \n\t" /* r2 = (num_words - 1) * 8 */ + "mov r9, %[r2] \n\t" /* r9 = (num_words - 1) * 8 */ + "movs %[r2], #0 \n\t" /* c0 = 0 */ + "movs %[r3], #0 \n\t" /* c1 = 0 */ + "movs %[r4], #0 \n\t" /* c2 = 0 */ + "movs %[r5], #0 \n\t" /* k = 0 */ + + "push {%[r0]} \n\t" /* keep result on the stack */ + + "1: \n\t" /* outer loop (k < num_words) */ + "movs %[r6], #0 \n\t" /* r6 = i = 0 */ + "b 3f \n\t" + + "2: \n\t" /* outer loop (k >= num_words) */ + "movs %[r6], %[r5] \n\t" /* r6 = k */ + "mov %[r0], r8 \n\t" /* r0 = (num_words - 1) * 4 */ + "subs %[r6], %[r0] \n\t" /* r6 = i = k - (num_words - 1) (times 4) */ + + "3: \n\t" /* inner loop */ + "mov r10, %[r2] \n\t" + "mov r11, %[r3] \n\t" + "mov r12, %[r4] \n\t" + "mov r14, %[r5] \n\t" + "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */ + + "ldr %[r3], [%[r1], %[r7]] \n\t" /* r3 = left[k - i] */ + "ldr %[r0], [%[r1], %[r6]] \n\t" /* r0 = left[i] */ + + "lsrs %[r2], %[r0], #16 \n\t" /* r2 = a1 */ + "uxth %[r0], %[r0] \n\t" /* r0 = a0 */ + + "lsrs %[r4], %[r3], #16 \n\t" /* r4 = b1 */ + "uxth %[r3], %[r3] \n\t" /* r3 = b0 */ + + "movs %[r5], %[r2] \n\t" /* r5 = a1 */ + "muls %[r5], %[r4], %[r5] \n\t" /* r5 = a1 * b1 */ + "muls %[r2], %[r3], %[r2] \n\t" /* r2 = b0 * a1 */ + "muls %[r4], %[r0], %[r4] \n\t" /* r4 = a0 * b1 */ + "muls %[r0], %[r3], %[r0] \n\t" /* r0 = a0 * b0 */ + + /* Add middle terms */ + "lsls %[r3], %[r2], #16 \n\t" + "lsrs %[r2], %[r2], #16 \n\t" + "adds %[r0], %[r3] \n\t" + "adcs %[r5], %[r2] \n\t" + + "lsls %[r3], %[r4], #16 \n\t" + "lsrs %[r4], %[r4], #16 \n\t" + "adds %[r0], %[r3] \n\t" + "adcs %[r5], %[r4] \n\t" + + /* Add to acc, doubling if necessary */ + "mov %[r2], r10\n\t" + "mov %[r3], r11\n\t" + "mov %[r4], r12\n\t" + + "cmp %[r6], %[r7] \n\t" /* (i < k - i) ? */ + "bge 4f \n\t" /* if i >= k - i, skip */ + "movs %[r7], #0 \n\t" /* r7 = 0 */ + "adds %[r2], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */ + "adcs %[r4], %[r7] \n\t" /* add carry to c2 */ + "4: \n\t" + "movs %[r7], #0 \n\t" /* r7 = 0 */ + "adds %[r2], %[r0] \n\t" /* add low word to c0 */ + "adcs %[r3], %[r5] \n\t" /* add high word to c1, including carry */ + "adcs %[r4], %[r7] \n\t" /* add carry to c2 */ + + "mov %[r5], r14\n\t" /* r5 = k */ + + "adds %[r6], #4 \n\t" /* i += 4 */ + "cmp %[r6], %[r5] \n\t" /* i >= k? */ + "bge 5f \n\t" /* if so, exit the loop */ + "subs %[r7], %[r5], %[r6] \n\t" /* r7 = k - i */ + "cmp %[r6], %[r7] \n\t" /* i <= k - i? */ + "ble 3b \n\t" /* if so, continue looping */ + + "5: \n\t" /* end inner loop */ + + "ldr %[r0], [sp, #0] \n\t" /* r0 = result */ + + "str %[r2], [%[r0], %[r5]] \n\t" /* result[k] = c0 */ + "mov %[r2], %[r3] \n\t" /* c0 = c1 */ + "mov %[r3], %[r4] \n\t" /* c1 = c2 */ + "movs %[r4], #0 \n\t" /* c2 = 0 */ + "adds %[r5], #4 \n\t" /* k += 4 */ + "cmp %[r5], r8 \n\t" /* k <= (num_words - 1) (times 4) ? */ + "ble 1b \n\t" /* if so, loop back, start with i = 0 */ + "cmp %[r5], r9 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */ + "ble 2b \n\t" /* if so, loop back, with i = (k + 1) - num_words */ + /* end outer loop */ + + "str %[r2], [%[r0], %[r5]] \n\t" /* result[num_words * 2 - 1] = c0 */ + "pop {%[r0]} \n\t" /* pop result off the stack */ + + RESUME_SYNTAX + : [r2] "+l" (num_words), [r3] "=&l" (r3), [r4] "=&l" (r4), + [r5] "=&l" (r5), [r6] "=&l" (r6), [r7] "=&l" (r7) + : [r0] "l" (result), [r1] "l" (left) + : "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory" + ); +#endif +} +#define asm_square 1 +#endif +#endif /* uECC_SQUARE_FUNC */ + +#endif /* _UECC_ASM_ARM_H_ */ diff --git a/core/embed/ble_firmware/uecc/asm_arm_mult_square.inc b/core/embed/ble_firmware/uecc/asm_arm_mult_square.inc new file mode 100644 index 000000000..8907fc185 --- /dev/null +++ b/core/embed/ble_firmware/uecc/asm_arm_mult_square.inc @@ -0,0 +1,2311 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_ +#define _UECC_ASM_ARM_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_5 \ + "push {r3} \n\t" \ + "add r0, 12 \n\t" \ + "add r2, 12 \n\t" \ + "ldmia r1!, {r3,r4} \n\t" \ + "ldmia r2!, {r6,r7} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adc r10, r10, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 28 \n\t" \ + "sub r2, 20 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + "ldmia r1!, {r5} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adc r11, r11, r9 \n\t" \ + "stmia r0!, {r10, r11} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_5_TO_6 \ + "cmp r3, #5 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + "sub r2, #20 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r14 \n\t" \ + "adc r12, r12, r9 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_6 \ + "push {r3} \n\t" \ + "add r0, 12 \n\t" \ + "add r2, 12 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + \ + "sub r0, 36 \n\t" \ + "sub r2, 24 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adc r14, r14, r11 \n\t" \ + "stmia r0!, {r12, r14} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_6_TO_7 \ + "cmp r3, #6 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "sub r2, #24 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_7 \ + "push {r3} \n\t" \ + "add r0, 24 \n\t" \ + "add r2, 24 \n\t" \ + "ldmia r1!, {r3} \n\t" \ + "ldmia r2!, {r6} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 20 \n\t" \ + "sub r2, 16 \n\t" \ + "ldmia r2!, {r6, r7, r8} \n\t" \ + "ldmia r1!, {r4, r5} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r12, r3, r7 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r9, r11, r4, r6 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adcs r12, r12, r11 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + \ + "sub r0, 44 \n\t" \ + "sub r1, 16 \n\t" \ + "sub r2, 28 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r9, r10, r3, r6 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r12, r3, r7 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r9, r11, r4, r6 \n\t" \ + "adds r10, r10, r9 \n\t" \ + "adcs r12, r12, r11 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r4, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r4, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "umull r10, r11, r3, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adc r14, r14, r11 \n\t" \ + "stmia r0!, {r12, r14} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_7_TO_8 \ + "cmp r3, #7 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high, r5 = right high */ \ + "ldr r4, [r1] \n\t" \ + "ldr r5, [r2] \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "sub r2, #28 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r10, r10, r6 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r9, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r10, r10, r11 \n\t" \ + "adcs r14, r14, r12 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r14, r14, r6 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "ldr r7, [r1], #4 \n\t" \ + "ldr r8, [r2], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "ldr r6, [r0] \n\t" \ + "adds r9, r9, r6 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + /* skip past already-loaded (r4, r5) */ \ + "ldr r7, [r1], #8 \n\t" \ + "ldr r8, [r2], #8 \n\t" \ + "mov r14, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r9, r9, r11 \n\t" \ + "adcs r10, r10, r12 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "umull r11, r12, r4, r5 \n\t" \ + "adds r11, r11, r10 \n\t" \ + "adc r12, r12, r14 \n\t" \ + "stmia r0!, {r11, r12} \n\t" + +#define FAST_MULT_ASM_8 \ + "push {r3} \n\t" \ + "add r0, 24 \n\t" \ + "add r2, 24 \n\t" \ + "ldmia r1!, {r3,r4} \n\t" \ + "ldmia r2!, {r6,r7} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adc r10, r10, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + \ + "sub r0, 28 \n\t" \ + "sub r2, 20 \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + "ldmia r1!, {r5} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adc r11, r11, r9 \n\t" \ + "stmia r0!, {r10, r11} \n\t" \ + \ + "sub r0, 52 \n\t" \ + "sub r1, 20 \n\t" \ + "sub r2, 32 \n\t" \ + "ldmia r1!, {r3,r4,r5} \n\t" \ + "ldmia r2!, {r6,r7,r8} \n\t" \ + \ + "umull r11, r12, r3, r6 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r9, r3, r7 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r11, r14, r4, r6 \n\t" \ + "adds r12, r12, r11 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r3, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r5, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r4, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r5, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r1!, {r5} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r3, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r5, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r4, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r5, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r1!, {r4} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r5, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r3, r8 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r14, #0 \n\t" \ + "umull r9, r10, r5, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r3, r6 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "umull r9, r10, r4, r8 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "ldr r9, [r0] \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adcs r12, r12, #0 \n\t" \ + "adc r14, r14, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "ldmia r2!, {r8} \n\t" \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r5, r8 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r3, r7 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "umull r10, r11, r4, r6 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "ldr r10, [r0] \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r14, r14, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "ldmia r2!, {r6} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r5, r6 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r8 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r4, r7 \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "ldr r11, [r0] \n\t" \ + "adds r14, r14, r11 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r14} \n\t" \ + \ + "ldmia r2!, {r7} \n\t" \ + "mov r11, #0 \n\t" \ + "umull r12, r14, r5, r7 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r3, r6 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "umull r12, r14, r4, r8 \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, r14 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "ldr r12, [r0] \n\t" \ + "adds r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r9} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r14, r9, r3, r7 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r14, r9, r4, r6 \n\t" \ + "adds r10, r10, r14 \n\t" \ + "adcs r11, r11, r9 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r10} \n\t" \ + \ + "umull r9, r10, r4, r7 \n\t" \ + "adds r11, r11, r9 \n\t" \ + "adc r12, r12, r10 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + "pop {r3} \n\t" + +#define FAST_SQUARE_ASM_5 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6} \n\t" \ + "push {r1} \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "umull r1, r14, r3, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "umull r1, r14, r3, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r4, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r6 \n\t" \ + "umull r1, r14, r4, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r4, r6 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r5, r5 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r5, r6 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r6, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_5_TO_6 \ + "cmp r2, #5 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11} \n\t" \ + "umull r3, r4, r6, r11 \n\t" \ + "umull r6, r5, r7, r11 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r11 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r11 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r11 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r9, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r14, [r0], #4 \n\t" \ + "adds r3, r3, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r4, r4, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r5, r5, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r6, r6, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r7, r7, r14 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r8, r9, r11, r11 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t" + +#define FAST_SQUARE_ASM_6 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t" \ + "push {r1} \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "umull r1, r14, r3, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "umull r1, r14, r3, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r4, r4 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "umull r1, r14, r3, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "umull r1, r14, r4, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "umull r1, r14, r4, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "umull r1, r14, r5, r5 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r9, r9, r14 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r4, r7 \n\t" \ + "umull r1, r14, r5, r6 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r14 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r5, r7 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r6, r6 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r6, r7 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r7, r7 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_6_TO_7 \ + "cmp r2, #6 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12} \n\t" \ + "umull r3, r4, r6, r12 \n\t" \ + "umull r6, r5, r7, r12 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r12 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r12 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r12 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "umull r10, r9, r11, r12 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r10, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r14, [r0], #4 \n\t" \ + "adds r3, r3, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r4, r4, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r5, r5, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r6, r6, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r7, r7, r14 \n\t" \ + "ldr r14, [r0], #4 \n\t" \ + "adcs r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r9, r10, r12, r12 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t" + +#define FAST_SQUARE_ASM_7 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2, r3, r4, r5, r6, r7, r8} \n\t" \ + "push {r1} \n\t" \ + "sub r1, 4 \n\t" \ + \ + "add r0, 24 \n\t" \ + "umull r9, r10, r2, r8 \n\t" \ + "stmia r0!, {r9, r10} \n\t" \ + "sub r0, 32 \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r4 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r3, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r4 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r5 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r2} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r4, r2 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r5, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r6, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r6, r2 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r7, r7 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r7, r2 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r2, r2 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_7_TO_8 \ + "cmp r2, #7 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r6,r7,r8,r9,r10,r11,r12,r14} \n\t" \ + "umull r3, r4, r6, r14 \n\t" \ + "umull r6, r5, r7, r14 \n\t" \ + "adds r4, r4, r6 \n\t" \ + "umull r7, r6, r8, r14 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "umull r8, r7, r9, r14 \n\t" \ + "adcs r6, r6, r8 \n\t" \ + "umull r9, r8, r10, r14 \n\t" \ + "adcs r7, r7, r9 \n\t" \ + "umull r10, r9, r11, r14 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "umull r11, r10, r12, r14 \n\t" \ + "adcs r9, r9, r11 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r11, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r10, r11, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t" + +#define FAST_SQUARE_ASM_8 \ + "push {r2} \n\t" \ + "ldmia r1!, {r2,r3,r4,r5,r6,r7,r8,r9} \n\t" \ + "push {r1} \n\t" \ + "sub r1, 8 \n\t" \ + \ + "add r0, 24 \n\t" \ + "umull r10, r11, r2, r8 \n\t" \ + "umull r12, r14, r2, r9 \n\t" \ + "umull r8, r9, r3, r9 \n\t" \ + "adds r11, r11, r12 \n\t" \ + "adcs r12, r14, r8 \n\t" \ + "adcs r14, r9, #0 \n\t" \ + "stmia r0!, {r10, r11, r12, r14} \n\t" \ + "sub r0, 40 \n\t" \ + \ + "umull r11, r12, r2, r2 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umull r10, r11, r2, r3 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r11, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r12, r12, r10 \n\t" \ + "adcs r8, r8, r11 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r11, r12, r2, r4 \n\t" \ + "adds r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "umull r11, r12, r3, r3 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r5 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r4 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r2, r6 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r3, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r4 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r2, r7 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r3, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r5 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r2} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r3, r7 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r4, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r5 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r3, r2 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r4, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r6 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "ldmia r1!, {r3} \n\t" \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r4, r2 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r5, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r6 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r4, r3 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r5, r2 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r6, r7 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "ldr r14, [r0] \n\t" \ + "adds r8, r8, r14 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umull r8, r9, r5, r3 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r6, r2 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adc r10, r10, r10 \n\t" \ + "mov r14, r9 \n\t" \ + "umlal r8, r9, r7, r7 \n\t" \ + "cmp r14, r9 \n\t" \ + "it hi \n\t" \ + "adchi r10, r10, #0 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umull r8, r11, r6, r3 \n\t" \ + "mov r14, r11 \n\t" \ + "umlal r8, r11, r7, r2 \n\t" \ + "cmp r14, r11 \n\t" \ + "it hi \n\t" \ + "adchi r12, r12, #0 \n\t" \ + "adds r8, r8, r8 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adc r12, r12, r12 \n\t" \ + "adds r8, r8, r9 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "adc r12, r12, #0 \n\t" \ + "stmia r0!, {r8} \n\t" \ + \ + "mov r8, #0 \n\t" \ + "umull r1, r10, r7, r3 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "umull r1, r10, r2, r2 \n\t" \ + "adds r11, r11, r1 \n\t" \ + "adcs r12, r12, r10 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "stmia r0!, {r11} \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umull r1, r10, r2, r3 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "adds r12, r12, r1 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "adc r11, r11, #0 \n\t" \ + "stmia r0!, {r12} \n\t" \ + \ + "umull r1, r10, r3, r3 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "adcs r11, r11, r10 \n\t" \ + "stmia r0!, {r8, r11} \n\t" \ + "pop {r1, r2} \n\t" + +#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */ diff --git a/core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc b/core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc new file mode 100644 index 000000000..c554d20e3 --- /dev/null +++ b/core/embed/ble_firmware/uecc/asm_arm_mult_square_umaal.inc @@ -0,0 +1,1202 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_ARM_MULT_SQUARE_H_ +#define _UECC_ASM_ARM_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_5 \ + "push {r3} \n\t" \ + "ldmia r2!, {r3, r4, r5, r6, r7} \n\t" \ + "push {r2} \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "umull r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "mov r14, #0 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "ldr r2, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r3, r2 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r2 \n\t" \ + "umaal r10, r11, r5, r2 \n\t" \ + "umaal r11, r12, r6, r2 \n\t" \ + "umaal r12, r14, r7, r2 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "str r14, [r0], #4 \n\t" \ + \ + "pop {r2, r3} \n\t" + +#define FAST_MULT_ASM_5_TO_6 \ + "cmp r3, #5 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + "sub r2, #20 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r12, r5, r4, r14 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "stmia r0!, {r9, r10} \n\t" + +#define FAST_MULT_ASM_6 \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" + +#define FAST_MULT_ASM_6_TO_7 \ + "cmp r3, #6 \n\t" \ + "beq 1f \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + "sub r2, #24 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r11, [r0], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r12, r5, r4, r14 \n\t" \ + "str r12, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "str r9, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "stmia r0!, {r10, r11} \n\t" + +#define FAST_MULT_ASM_7 \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "ldmia r2!, {r4, r5, r6} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" + +#define FAST_MULT_ASM_7_TO_8 \ + "cmp r3, #7 \n\t" \ + "beq 1f \n\t" \ + "push {r3} \n\t" \ + \ + /* r4 = left high */ \ + "ldr r4, [r1] \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + "sub r2, #28 \n\t" \ + \ + /* Do right side */ \ + "ldr r14, [r2], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r0], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r7, [r0], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r8, [r0], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r9, [r0], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r10, [r0], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r11, [r0], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "ldr r14, [r2], #4 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "umaal r11, r12, r4, r14 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* r4 = right high */ \ + "ldr r4, [r2], #4 \n\t" \ + \ + /* Do left side */ \ + "ldr r14, [r1], #4 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r3, r5, r4, r14 \n\t" \ + "str r3, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r5, r6, r4, r14 \n\t" \ + "str r5, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r6, r7, r4, r14 \n\t" \ + "str r6, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r7, r8, r4, r14 \n\t" \ + "str r7, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r9, r10, r4, r14 \n\t" \ + "str r9, [r0], #4 \n\t" \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r10, r11, r4, r14 \n\t" \ + "str r10, [r0], #4 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umaal r11, r12, r4, r14 \n\t" \ + "stmia r0!, {r11, r12} \n\t" \ + "pop {r3} \n\t" + +#define FAST_MULT_ASM_8 \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "umull r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" \ + \ + "sub r0, #32 \n\t" \ + "sub r1, #32 \n\t" \ + "ldmia r2!, {r4, r5, r6, r7} \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "mov r11, #0 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "mov r12, #0 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "ldr r14, [r1], #4 \n\t" \ + "ldr r8, [r0] \n\t" \ + "umaal r8, r9, r4, r14 \n\t" \ + "str r8, [r0], #4 \n\t" \ + "umaal r9, r10, r5, r14 \n\t" \ + "umaal r10, r11, r6, r14 \n\t" \ + "umaal r11, r12, r7, r14 \n\t" \ + \ + "str r9, [r0], #4 \n\t" \ + "str r10, [r0], #4 \n\t" \ + "str r11, [r0], #4 \n\t" \ + "str r12, [r0], #4 \n\t" + +#define FAST_SQUARE_ASM_5 \ + "ldmia r1!, {r9,r10,r11,r12,r14} \n\t" \ + "push {r1, r2} \n\t" \ + \ + "umull r1, r2, r10, r9 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r11, r9 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r9 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r14, r9 \n\t" \ + \ + "mov r6, #0 \n\t" \ + "umaal r6, r3, r11, r10 \n\t" \ + "umaal r3, r4, r12, r10 \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + \ + "umull r7, r8, r9, r9 \n\t" \ + /* Store carry in r9 */ \ + "mov r9, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + "adds r8, r8, r1 \n\t" \ + "stmia r0!, {r7,r8} \n\t" \ + \ + "umull r7, r8, r10, r10 \n\t" \ + "adcs r7, r7, r2 \n\t" \ + "adcs r8, r8, r6 \n\t" \ + "stmia r0!, {r7,r8} \n\t" \ + \ + "umaal r4, r5, r14, r10 \n\t" \ + /* Store carry in r10 */ \ + "mov r10, #0 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r12, r11 \n\t" \ + "umaal r4, r5, r14, r11 \n\t" \ + \ + "mov r2, #0 \n\t" \ + "umaal r2, r5, r14, r12 \n\t" \ + /* Load carry from r9 */ \ + "lsrs r9, #1 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + /* r9 is 0 now */ \ + "adc r9, r9, #0 \n\t" \ + \ + /* Use carry from r10 */ \ + "umaal r3, r10, r11, r11 \n\t" \ + "adds r10, r10, r1 \n\t" \ + "stmia r0!, {r3,r10} \n\t" \ + \ + "umull r6, r10, r12, r12 \n\t" \ + "adcs r6, r6, r4 \n\t" \ + "adcs r10, r10, r2 \n\t" \ + "stmia r0!, {r6,r10} \n\t" \ + \ + "umull r6, r10, r14, r14 \n\t" \ + "adcs r6, r6, r5 \n\t" \ + "adcs r10, r10, r9 \n\t" \ + "stmia r0!, {r6,r10} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_5_TO_6 \ + "cmp r2, #5 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #20 \n\t" \ + "sub r1, #20 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r9, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "adcs r8, r8, #0 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "sub r0, #20 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r8, r9, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9} \n\t" + +#define FAST_SQUARE_ASM_6 \ + "ldmia r1!, {r8,r9,r10,r11,r12,r14} \n\t" \ + "push {r1, r2} \n\t" \ + \ + "umull r1, r2, r9, r8 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r10, r8 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r11, r8 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r12, r8 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r14, r8 \n\t" \ + \ + "mov r7, #0 \n\t" \ + "umaal r7, r3, r10, r9 \n\t" \ + "umaal r3, r4, r11, r9 \n\t" \ + "umaal r4, r5, r12, r9 \n\t" \ + "push {r4, r5} \n\t" \ + "adds r1, r1, r1 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + \ + "umull r4, r5, r8, r8 \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + "adds r5, r5, r1 \n\t" \ + "stmia r0!, {r4,r5} \n\t" \ + \ + "umull r4, r5, r9, r9 \n\t" \ + "adcs r4, r4, r2 \n\t" \ + "adcs r5, r5, r7 \n\t" \ + "stmia r0!, {r4,r5} \n\t" \ + \ + "pop {r4, r5} \n\t" \ + "umaal r5, r6, r14, r9 \n\t" \ + /* Store carry in r9 */ \ + "mov r9, #0 \n\t" \ + "adc r9, r9, #0 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r11, r10 \n\t" \ + "umaal r4, r5, r12, r10 \n\t" \ + "umaal r5, r6, r14, r10 \n\t" \ + \ + "mov r2, #0 \n\t" \ + "umaal r2, r5, r12, r11 \n\t" \ + "umaal r5, r6, r14, r11 \n\t" \ + \ + "mov r7, #0 \n\t" \ + "umaal r7, r6, r14, r12 \n\t" \ + \ + /* Load carry from r8 */ \ + "lsrs r8, #1 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + /* Use carry from r9 */ \ + "umaal r3, r9, r10, r10 \n\t" \ + "adds r9, r9, r1 \n\t" \ + "stmia r0!, {r3,r9} \n\t" \ + \ + "umull r9, r10, r11, r11 \n\t" \ + "adcs r9, r9, r4 \n\t" \ + "adcs r10, r10, r2 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + \ + "umull r9, r10, r12, r12 \n\t" \ + "adcs r9, r9, r5 \n\t" \ + "adcs r10, r10, r7 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + \ + "umull r9, r10, r14, r14 \n\t" \ + "adcs r9, r9, r6 \n\t" \ + "adcs r10, r10, r8 \n\t" \ + "stmia r0!, {r9,r10} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_6_TO_7 \ + "cmp r2, #6 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #24 \n\t" \ + "sub r1, #24 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r10,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r10, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r10, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "adcs r9, r9, #0 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "sub r0, #24 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r9, r10, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10} \n\t" + +#define FAST_SQUARE_ASM_7 \ + "ldmia r1!, {r9,r10,r11,r12} \n\t" \ + "push {r2} \n\t" \ + \ + "umull r14, r2, r10, r9 \n\t" \ + "mov r3, #0 \n\t" \ + "umaal r2, r3, r11, r9 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r9 \n\t" \ + \ + "mov r5, #0 \n\t" \ + "umaal r5, r3, r11, r10 \n\t" \ + "adds r14, r14, r14 \n\t" \ + "adcs r2, r2, r2 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + /* Store carry in r7 */ \ + "mov r7, #0 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + "umull r6, r8, r9, r9 \n\t" \ + "adds r8, r8, r14 \n\t" \ + "stmia r0!, {r6,r8} \n\t" \ + \ + "umull r6, r8, r10, r10 \n\t" \ + "adcs r6, r6, r2 \n\t" \ + "adcs r8, r8, r5 \n\t" \ + "stmia r0!, {r6,r8} \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "ldmia r1!, {r2, r6, r14} \n\t" \ + "push {r1} \n\t" \ + "umaal r3, r4, r2, r9 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r9 \n\t" \ + "mov r1, #0 \n\t" \ + "umaal r5, r1, r14, r9 \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umaal r3, r9, r12, r10 \n\t" \ + "umaal r9, r4, r2, r10 \n\t" \ + "umaal r4, r5, r6, r10 \n\t" \ + "umaal r5, r1, r14, r10 \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umaal r10, r9, r12, r11 \n\t" \ + "umaal r9, r4, r2, r11 \n\t" \ + "umaal r4, r5, r6, r11 \n\t" \ + "umaal r5, r1, r14, r11 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + /* Store carry back in r7 */ \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r3, r8, r11, r11 \n\t" \ + "adds r8, r8, r10 \n\t" \ + "stmia r0!, {r3,r8} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "mov r3, #0 \n\t" \ + "umaal r3, r4, r2, r12 \n\t" \ + "umaal r4, r5, r6, r12 \n\t" \ + "umaal r5, r1, r14, r12 \n\t" \ + \ + "mov r10, #0 \n\t" \ + "umaal r10, r5, r6, r2 \n\t" \ + "umaal r5, r1, r14, r2 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r1, r14, r6 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r9, r12, r12 \n\t" \ + "adds r9, r9, r3 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r2, r2 \n\t" \ + "adcs r8, r8, r4 \n\t" \ + "adcs r9, r9, r10 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r6, r6 \n\t" \ + "adcs r8, r8, r5 \n\t" \ + "adcs r9, r9, r11 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r14, r14 \n\t" \ + "adcs r8, r8, r1 \n\t" \ + "adcs r9, r9, r7 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + "pop {r1, r2} \n\t" + +#define FAST_SQUARE_ASM_7_TO_8 \ + "cmp r2, #7 \n\t" \ + "beq 1f \n\t" \ + \ + "sub r0, #28 \n\t" \ + "sub r1, #28 \n\t" \ + \ + /* Do off-center multiplication */ \ + "ldmia r1!, {r5,r6,r7,r8,r9,r10,r11,r14} \n\t" \ + "umull r3, r4, r5, r14 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r6, r14 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r7, r14 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r8, r14 \n\t" \ + "mov r8, #0 \n\t" \ + "umaal r7, r8, r9, r14 \n\t" \ + "mov r9, #0 \n\t" \ + "umaal r8, r9, r10, r14 \n\t" \ + "mov r10, #0 \n\t" \ + "umaal r9, r10, r11, r14 \n\t" \ + \ + /* Multiply by 2 */ \ + "mov r11, #0 \n\t" \ + "adds r3, r3, r3 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adcs r8, r8, r8 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r10, r10, r10 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + \ + /* Add into previous */ \ + "ldr r12, [r0], #4 \n\t" \ + "adds r3, r3, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r4, r4, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r5, r5, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r6, r6, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r7, r7, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "ldr r12, [r0], #4 \n\t" \ + "adcs r9, r9, r12 \n\t" \ + "adcs r10, r10, #0 \n\t" \ + "adcs r11, r11, #0 \n\t" \ + "sub r0, #28 \n\t" \ + \ + /* Perform center multiplication */ \ + "umlal r10, r11, r14, r14 \n\t" \ + "stmia r0!, {r3,r4,r5,r6,r7,r8,r9,r10,r11} \n\t" + +#define FAST_SQUARE_ASM_8 \ + "ldmia r1!, {r10,r11,r12,r14} \n\t" \ + "push {r2} \n\t" \ + \ + "umull r2, r3, r11, r10 \n\t" \ + "mov r4, #0 \n\t" \ + "umaal r3, r4, r12, r10 \n\t" \ + "mov r5, #0 \n\t" \ + "umaal r4, r5, r14, r10 \n\t" \ + \ + "mov r6, #0 \n\t" \ + "umaal r6, r4, r12, r11 \n\t" \ + "adds r2, r2, r2 \n\t" \ + "adcs r3, r3, r3 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + /* Store carry in r7 */ \ + "mov r7, #0 \n\t" \ + "adc r7, r7, #0 \n\t" \ + \ + "umull r8, r9, r10, r10 \n\t" \ + "adds r9, r9, r2 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + \ + "umull r8, r9, r11, r11 \n\t" \ + "adcs r8, r8, r3 \n\t" \ + "adcs r9, r9, r6 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + /* Store carry in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "ldmia r1!, {r2, r3} \n\t" \ + "push {r1} \n\t" \ + "umaal r4, r5, r2, r10 \n\t" \ + "mov r6, #0 \n\t" \ + "umaal r5, r6, r3, r10 \n\t" \ + \ + "mov r9, #0 \n\t" \ + "umaal r9, r4, r14, r11 \n\t" \ + "umaal r4, r5, r2, r11 \n\t" \ + \ + "mov r1, #0 \n\t" \ + "umaal r1, r4, r14, r12 \n\t" \ + \ + /* Load carry from r7 */ \ + "lsrs r7, #1 \n\t" \ + "adcs r9, r9, r9 \n\t" \ + "adcs r1, r1, r1 \n\t" \ + /* Store carry back in r7 */ \ + "adc r7, r7, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r9, r12, r12 \n\t" \ + "adds r9, r9, r1 \n\t" \ + "stmia r0!, {r8,r9} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "pop {r1} \n\t" \ + /* TODO could fix up r1 value on stack here */ \ + /* and leave the value on the stack (rather */ \ + /* than popping) if supporting curves > 256 bits */ \ + "ldr r9, [r1], #4 \n\t" \ + "ldr r1, [r1] \n\t" \ + \ + "push {r7} \n\t" \ + "umaal r5, r6, r9, r10 \n\t" \ + "mov r7, #0 \n\t" \ + "umaal r6, r7, r1, r10 \n\t" \ + /* Carry now stored in r10 */ \ + "pop {r10} \n\t" \ + \ + "umaal r4, r5, r3, r11 \n\t" \ + "umaal r5, r6, r9, r11 \n\t" \ + "umaal r6, r7, r1, r11 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r4, r2, r12 \n\t" \ + "umaal r4, r5, r3, r12 \n\t" \ + "umaal r5, r6, r9, r12 \n\t" \ + "umaal r6, r7, r1, r12 \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umaal r12, r4, r2, r14 \n\t" \ + "umaal r4, r5, r3, r14 \n\t" \ + "umaal r5, r6, r9, r14 \n\t" \ + "umaal r6, r7, r1, r14 \n\t" \ + \ + /* Load carry from r10 */ \ + "lsrs r10, #1 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r8, r11, r14, r14 \n\t" \ + "adds r11, r11, r12 \n\t" \ + "stmia r0!, {r8,r11} \n\t" \ + /* Store carry back in r8 */ \ + "mov r8, #0 \n\t" \ + "adc r8, r8, #0 \n\t" \ + \ + "mov r11, #0 \n\t" \ + "umaal r11, r5, r3, r2 \n\t" \ + "umaal r5, r6, r9, r2 \n\t" \ + "umaal r6, r7, r1, r2 \n\t" \ + \ + "mov r12, #0 \n\t" \ + "umaal r12, r6, r9, r3 \n\t" \ + "umaal r6, r7, r1, r3 \n\t" \ + \ + "mov r14, #0 \n\t" \ + "umaal r14, r7, r1, r9 \n\t" \ + \ + /* Load carry from r10 */ \ + "lsrs r10, #1 \n\t" \ + "adcs r4, r4, r4 \n\t" \ + "adcs r11, r11, r11 \n\t" \ + "adcs r5, r5, r5 \n\t" \ + "adcs r12, r12, r12 \n\t" \ + "adcs r6, r6, r6 \n\t" \ + "adcs r14, r14, r14 \n\t" \ + "adcs r7, r7, r7 \n\t" \ + "adc r10, r10, #0 \n\t" \ + \ + /* Use carry from r8 */ \ + "umaal r4, r8, r2, r2 \n\t" \ + "adds r8, r8, r11 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r3, r3 \n\t" \ + "adcs r4, r4, r5 \n\t" \ + "adcs r8, r8, r12 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r9, r9 \n\t" \ + "adcs r4, r4, r6 \n\t" \ + "adcs r8, r8, r14 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + \ + "umull r4, r8, r1, r1 \n\t" \ + "adcs r4, r4, r7 \n\t" \ + "adcs r8, r8, r10 \n\t" \ + "stmia r0!, {r4,r8} \n\t" \ + /* TODO pop {r1, r2} if supporting curves > 256 bits */ \ + "pop {r2} \n\t" + +#endif /* _UECC_ASM_ARM_MULT_SQUARE_H_ */ diff --git a/core/embed/ble_firmware/uecc/asm_avr.inc b/core/embed/ble_firmware/uecc/asm_avr.inc new file mode 100644 index 000000000..c14bf5554 --- /dev/null +++ b/core/embed/ble_firmware/uecc/asm_avr.inc @@ -0,0 +1,1089 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_AVR_H_ +#define _UECC_ASM_AVR_H_ + +#if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #define uECC_MIN_WORDS 32 +#endif +#if uECC_SUPPORTS_secp224r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 28 +#endif +#if uECC_SUPPORTS_secp192r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 24 +#endif +#if uECC_SUPPORTS_secp160r1 + #undef uECC_MIN_WORDS + #define uECC_MIN_WORDS 20 +#endif + +#if __AVR_HAVE_EIJMP_EICALL__ + #define IJMP "eijmp \n\t" +#else + #define IJMP "ijmp \n\t" +#endif + +#if (uECC_OPTIMIZATION_LEVEL >= 2) + +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + volatile uECC_word_t *v = vli; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + IJMP + #endif + + REPEAT(uECC_MAX_WORDS, "st x+, __zero_reg__ \n\t") + "1: \n\t" + : "+x" (v) + : [num] "r" (num_words) + : + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "r30", "r31", "cc" + #endif + ); +} +#define asm_clear 1 + +uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) { + volatile uECC_word_t *d = dest; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + IJMP + #endif + + REPEAT(uECC_MAX_WORDS, + "ld r0, y+ \n\t" + "st x+, r0 \n\t") + "1: \n\t" + : "+x" (d), "+y" (src) + : [num] "r" ((uint8_t)(num_words * 2)) + : "r0" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + , "r30", "r31", "cc" + #endif + ); +} +#define asm_set 1 + +uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + volatile uECC_word_t *v = vli; + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(1f) \n\t" + "ldi r31, pm_hi8(1f) \n\t" + "sub r30, %[jump] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "add r26, %[num] \n\t" + "adc r27, __zero_reg__ \n\t" + "ld r0, -x \n\t" + "lsr r0 \n\t" + "st x, r0 \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + #endif + + REPEAT(DEC(uECC_MAX_WORDS), + "ld r0, -x \n\t" + "ror r0 \n\t" + "st x, r0 \n\t") + "1: \n\t" + : "+x" (v) + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + : [num] "r" (num_words), [jump] "r" ((uint8_t)(3 * (num_words - 1))) + : "r0", "r30", "r31", "cc" + #else + : [num] "r" (num_words) + : "r0", "cc" + #endif + ); +} +#define asm_rshift1 1 + +#define ADD_RJPM_TABLE(N) \ + "movw r30, %A[result] \n\t" \ + "rjmp add_%=_" #N " \n\t" + +#define ADD_RJPM_DEST(N) \ + "add_%=_" #N ":" \ + "ld %[clb], x+ \n\t" \ + "ld %[rb], y+ \n\t" \ + "adc %[clb], %[rb] \n\t" \ + "st z+, %[clb] \n\t" + +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry; + uint8_t right_byte; + + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "ldi r31, pm_hi8(add_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "clc \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + REPEATM(uECC_MAX_WORDS, ADD_RJPM_TABLE) + #endif + + REPEATM(uECC_MAX_WORDS, ADD_RJPM_DEST) + + "mov %[clb], __zero_reg__ \n\t" + "adc %[clb], %[clb] \n\t" /* Store carry bit. */ + + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) + : "r30", "r31", "cc" + ); + return carry; +} +#define asm_add 1 + +#define SUB_RJPM_TABLE(N) \ + "movw r30, %A[result] \n\t" \ + "rjmp sub_%=_" #N " \n\t" + +#define SUB_RJPM_DEST(N) \ + "sub_%=_" #N ":" \ + "ld %[clb], x+ \n\t" \ + "ld %[rb], y+ \n\t" \ + "sbc %[clb], %[rb] \n\t" \ + "st z+, %[clb] \n\t" + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry; + uint8_t right_byte; + + __asm__ volatile ( + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + "ldi r30, pm_lo8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "ldi r31, pm_hi8(sub_%=_" STR(uECC_MAX_WORDS) ") \n\t" + "sub r30, %[num] \n\t" + "sbc r31, __zero_reg__ \n\t" + #endif + + "clc \n\t" + #if (uECC_MAX_WORDS != uECC_MIN_WORDS) + IJMP + REPEATM(uECC_MAX_WORDS, SUB_RJPM_TABLE) + #endif + + REPEATM(uECC_MAX_WORDS, SUB_RJPM_DEST) + + "mov %[clb], __zero_reg__ \n\t" + "adc %[clb], %[clb] \n\t" /* Store carry bit. */ + + : "+x" (left), "+y" (right), + [clb] "=&r" (carry), [rb] "=&r" (right_byte) + : [result] "r" (r), [num] "r" ((uint8_t)(num_words * 2)) + : "r30", "r31", "cc" + ); + return carry; +} +#define asm_sub 1 + +#if (uECC_OPTIMIZATION_LEVEL >= 3) + +#include "asm_avr_mult_square.inc" + +__attribute((noinline)) +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + /* num_words should already be in r18. */ + register wordcount_t r18 __asm__("r18") = num_words; + + __asm__ volatile ( + "push r18 \n\t" +#if (uECC_MIN_WORDS == 20) + FAST_MULT_ASM_20 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 20) + FAST_MULT_ASM_20_TO_24 + #endif + #if (uECC_MAX_WORDS > 24) + FAST_MULT_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 24) + FAST_MULT_ASM_24 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 24) + FAST_MULT_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 28) + FAST_MULT_ASM_28 + "pop r18 \n\t" + #if (uECC_MAX_WORDS > 28) + FAST_MULT_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 32) + FAST_MULT_ASM_32 + "pop r18 \n\t" +#endif + "2: \n\t" + "eor r1, r1 \n\t" + : "+x" (left), "+y" (right), "+z" (result) + : "r" (r18) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r19", "r20", + "r21", "r22", "r23", "r24", "r25", "cc" + ); +} +#define asm_mult 1 + +#if uECC_SQUARE_FUNC +__attribute((noinline)) +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + /* num_words should already be in r20. */ + register wordcount_t r20 __asm__("r20") = num_words; + + __asm__ volatile ( + "push r20 \n\t" +#if (uECC_MIN_WORDS == 20) + FAST_SQUARE_ASM_20 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 20) + FAST_SQUARE_ASM_20_TO_24 + #endif + #if (uECC_MAX_WORDS > 24) + FAST_SQUARE_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 24) + FAST_SQUARE_ASM_24 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 24) + FAST_SQUARE_ASM_24_TO_28 + #endif + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 28) + FAST_SQUARE_ASM_28 + "pop r20 \n\t" + #if (uECC_MAX_WORDS > 28) + FAST_SQUARE_ASM_28_TO_32 + #endif +#elif (uECC_MIN_WORDS == 32) + FAST_SQUARE_ASM_32 + "pop r20 \n\t" +#endif + "2: \n\t" + "eor r1, r1 \n\t" + : "+x" (left), "+z" (result) + : "r" (r20) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", + "r21", "r22", "r23", "r24", "r25", "r28", "r29", "cc" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 3) */ + +#if uECC_SUPPORTS_secp160r1 +static const struct uECC_Curve_t curve_secp160r1; +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uint8_t carry = 0; + __asm__ volatile ( + "in r30, __SP_L__ \n\t" + "in r31, __SP_H__ \n\t" + "sbiw r30, 24 \n\t" + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + "adiw r30, 25 \n\t" /* we are shifting by 31 bits, so shift over 4 bytes + (+ 1 since z initially points below the stack) */ + "adiw r26, 40 \n\t" /* end of product */ + "ld r18, -x \n\t" /* Load word. */ + "lsr r18 \n\t" /* Shift. */ + "st -z, r18 \n\t" /* Store the first result word. */ + + /* Now we just do the remaining words with the carry bit (using ROR) */ + REPEAT(19, + "ld r18, -x \n\t" + "ror r18 \n\t" + "st -z, r18 \n\t") + + "eor r18, r18 \n\t" /* r18 = 0 */ + "ror r18 \n\t" /* get last bit */ + "st -z, r18 \n\t" /* store it */ + + "sbiw r30, 3 \n\t" /* move z back to point at tmp */ + /* now we add right */ + "ld r18, x+ \n\t" + "st z+, r18 \n\t" /* the first 3 bytes do not need to be added */ + "ld r18, x+ \n\t" + "st z+, r18 \n\t" + "ld r18, x+ \n\t" + "st z+, r18 \n\t" + + "ld r18, x+ \n\t" + "ld r19, z \n\t" + "add r18, r19 \n\t" + "st z+, r18 \n\t" + + /* Now we just do the remaining words with the carry bit (using ADC) */ + REPEAT(16, + "ld r18, x+ \n\t" + "ld r19, z \n\t" + "adc r18, r19 \n\t" + "st z+, r18 \n\t") + + /* Propagate over the remaining bytes of result */ + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "ld r18, z \n\t" + "adc r18, r1 \n\t" + "st z+, r18 \n\t" + + "sbiw r30, 24 \n\t" /* move z back to point at tmp */ + "sbiw r26, 40 \n\t" /* move x back to point at product */ + + /* add low bytes of tmp to product, storing in result */ + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(19, + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + /* at this point x is at the end of product, y is at the end of result, + z is 20 bytes into tmp */ + "sbiw r28, 20 \n\t" /* move y back to point at result */ + "adiw r30, 4 \n\t" /* move z to point to the end of tmp */ + + /* do omega_mult again with the 4 relevant bytes */ + /* z points to the end of tmp, x points to the end of product */ + "ld r18, -z \n\t" /* Load word. */ + "lsr r18 \n\t" /* Shift. */ + "st -x, r18 \n\t" /* Store the first result word. */ + + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + "ld r18, -z \n\t" + "ror r18 \n\t" + "st -x, r18 \n\t" + + "eor r18, r18 \n\t" /* r18 = 0 */ + "ror r18 \n\t" /* get last bit */ + "st -x, r18 \n\t" /* store it */ + + "sbiw r26, 3 \n\t" /* move x back to point at beginning */ + /* now we add a copy of the 4 bytes */ + "ld r18, z+ \n\t" + "st x+, r18 \n\t" /* the first 3 bytes do not need to be added */ + "ld r18, z+ \n\t" + "st x+, r18 \n\t" + "ld r18, z+ \n\t" + "st x+, r18 \n\t" + + "ld r18, z+ \n\t" + "ld r19, x \n\t" + "add r18, r19 \n\t" + "st x+, r18 \n\t" + + /* Propagate over the remaining bytes */ + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + "ld r18, x \n\t" + "adc r18, r1 \n\t" + "st x+, r18 \n\t" + + /* now z points to the end of tmp, x points to the end of product + (y still points at result) */ + "sbiw r26, 8 \n\t" /* move x back to point at beginning of actual data */ + /* add into result */ + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(7, + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + /* Done adding, now propagate carry bit */ + REPEAT(12, + "ld r18, y \n\t" + "adc r18, __zero_reg__ \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + "sbiw r28, 20 \n\t" /* move y back to point at result */ + + "sbiw r30, 1 \n\t" /* fix stack pointer */ + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) + : "r0", "r18", "r19", "r30", "r31", "cc" + ); + + if (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } + if (carry > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } + if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, 20) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, 20); + } +} +#define asm_mmod_fast_secp160r1 1 +#endif /* uECC_SUPPORTS_secp160r1 */ + +#if uECC_SUPPORTS_secp256k1 +static const struct uECC_Curve_t curve_secp256k1; +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + uint8_t carry = 0; + __asm__ volatile ( + "in r30, __SP_L__ \n\t" + "in r31, __SP_H__ \n\t" + "sbiw r30, 37 \n\t" + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + "adiw r30, 1 \n\t" /* add 1 since z initially points below the stack */ + "adiw r26, 32 \n\t" /* product + uECC_WORDS */ + "ldi r25, 0x03 \n\t" + "ldi r24, 0xD1 \n\t" + "ld r18, x+ \n\t" + "ld r19, x+ \n\t" + "ld r20, x+ \n\t" + "ld r21, x+ \n\t" + + "mul r24, r18 \n\t" + "st z+, r0 \n\t" + "mov r22, r1 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + /* now we start adding the 2^32 part as well */ + "add r23, r18 \n\t" // 28 + "adc r22, r22 \n\t" + "ld r18, x+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" // 27 + "adc r23, r23 \n\t" + "ld r19, x+ \n\t" + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + REPEAT(6, // 26 - 3 + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "ld r20, x+ \n\t" + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "ld r21, x+ \n\t" + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "ld r18, x+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "ld r19, x+ \n\t" + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t") + + "add r23, r20 \n\t" // 2 + "adc r22, r22 \n\t" + "ld r20, x+ \n\t" + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" // 1 + "adc r23, r23 \n\t" + "ld r21, x+ \n\t" + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + /* Now finish the carries etc */ + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "st z+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "st z+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "st z+, r22 \n\t" + "st z+, r23 \n\t" + "eor r1, r1 \n\t" /* make r1 be 0 again */ + + "sbiw r30, 37 \n\t" /* move z back to point at tmp */ + "subi r26, 64 \n\t" /* move x back to point at product */ + "sbc r27, __zero_reg__ \n\t" + + /* add low bytes of tmp to product, storing in result */ + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(31, + "ld r18, z+ \n\t" + "ld r19, x+ \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + /* at this point x is at the end of product, y is at the end of result, + z is 32 bytes into tmp */ + "sbiw r28, 32 \n\t" /* move y back to point at result */ + + /* do omega_mult again with the 5 relevant bytes */ + /* z points to tmp + uECC_WORDS, x points to the end of product */ + "sbiw r26, 32 \n\t" /* shift x back to point into the product buffer + (we can overwrite it now) */ + "ld r18, z+ \n\t" + "ld r19, z+ \n\t" + "ld r20, z+ \n\t" + "ld r21, z+ \n\t" + + "mul r24, r18 \n\t" + "st x+, r0 \n\t" + "mov r22, r1 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r19 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" /* can't overflow */ + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "mul r24, r20 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r19 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + "mul r24, r21 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "mul r25, r20 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "ld r18, z+ \n\t" + "mul r24, r18 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "mul r25, r21 \n\t" + "add r23, r0 \n\t" + "adc r22, r1 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + /* Now finish the carries etc */ + "add r22, r19 \n\t" + "adc r23, r23 \n\t" + "mul r25, r18 \n\t" + "add r22, r0 \n\t" + "adc r23, r1 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r20 \n\t" + "adc r22, r22 \n\t" + "st x+, r23 \n\t" + "ldi r23, 0 \n\t" + + "add r22, r21 \n\t" + "adc r23, r23 \n\t" + "st x+, r22 \n\t" + "ldi r22, 0 \n\t" + + "add r23, r18 \n\t" + "adc r22, r22 \n\t" + "st x+, r23 \n\t" + "st x+, r22 \n\t" + "eor r1, r1 \n\t" /* make r1 be 0 again */ + + /* now z points to the end of tmp, x points to the end of product + (y still points at result) */ + "sbiw r26, 10 \n\t" /* move x back to point at beginning of actual data */ + /* add into result */ + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "add r18, r19 \n\t" + "st y+, r18 \n\t" + REPEAT(9, + "ld r18, x+ \n\t" + "ld r19, y \n\t" + "adc r18, r19 \n\t" + "st y+, r18 \n\t") + + /* Done adding, now propagate carry bit */ + REPEAT(22, + "ld r18, y \n\t" + "adc r18, __zero_reg__ \n\t" + "st y+, r18 \n\t") + + "adc %[carry], __zero_reg__ \n\t" /* Store carry bit (carry flag is cleared). */ + "sbiw r28, 32 \n\t" /* move y back to point at result */ + + "sbiw r30, 1 \n\t" /* fix stack pointer */ + "in r0, __SREG__ \n\t" + "cli \n\t" + "out __SP_H__, r31 \n\t" + "out __SREG__, r0 \n\t" + "out __SP_L__, r30 \n\t" + + : "+x" (product), [carry] "+r" (carry) + : "y" (result) + : "r0", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r30", "r31", "cc" + ); + + if (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } + if (carry > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } + if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, 32) > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, 32); + } +} +#define asm_mmod_fast_secp256k1 1 +#endif /* uECC_SUPPORTS_secp256k1 */ + +#endif /* (uECC_OPTIMIZATION_LEVEL >= 2) */ + +/* ---- "Small" implementations ---- */ + +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t carry = 0; + uint8_t left_byte; + uint8_t right_byte; + + __asm__ volatile ( + "clc \n\t" + + "1: \n\t" + "ld %[left], x+ \n\t" /* Load left byte. */ + "ld %[right], y+ \n\t" /* Load right byte. */ + "adc %[left], %[right] \n\t" /* Add. */ + "st z+, %[left] \n\t" /* Store the result. */ + "dec %[i] \n\t" + "brne 1b \n\t" + + "adc %[carry], %[carry] \n\t" /* Store carry bit. */ + + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + [carry] "+r" (carry), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : + : "cc" + ); + return carry; +} +#define asm_add 1 +#endif + +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t borrow = 0; + uint8_t left_byte; + uint8_t right_byte; + + __asm__ volatile ( + "clc \n\t" + + "1: \n\t" + "ld %[left], x+ \n\t" /* Load left byte. */ + "ld %[right], y+ \n\t" /* Load right byte. */ + "sbc %[left], %[right] \n\t" /* Subtract. */ + "st z+, %[left] \n\t" /* Store the result. */ + "dec %[i] \n\t" + "brne 1b \n\t" + + "adc %[borrow], %[borrow] \n\t" /* Store carry bit in borrow. */ + + : "+z" (r), "+x" (left), "+y" (right), [i] "+r" (num_words), + [borrow] "+r" (borrow), [left] "=&r" (left_byte), [right] "=&r" (right_byte) + : + : "cc" + ); + return borrow; +} +#define asm_sub 1 +#endif + +#if !asm_mult +__attribute((noinline)) +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t r0 = 0; + uint8_t r1 = 0; + uint8_t r2 = 0; + uint8_t zero = 0; + uint8_t k, i; + + __asm__ volatile ( + "ldi %[k], 1 \n\t" /* k = 1; k < num_words; ++k */ + + "1: \n\t" + "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ + + "add r28, %[k] \n\t" /* pre-add right ptr */ + "adc r29, %[zero] \n\t" + + "2: \n\t" + "ld r0, x+ \n\t" + "ld r1, -y \n\t" + "mul r0, r1 \n\t" + + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "inc %[i] \n\t" + "cp %[i], %[k] \n\t" + "brlo 2b \n\t" /* loop if i < k */ + + "sub r26, %[k] \n\t" /* fix up left ptr */ + "sbc r27, %[zero] \n\t" + + "st z+, %[r0] \n\t" /* Store the result. */ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "inc %[k] \n\t" + "cp %[k], %[num] \n\t" + "brlo 1b \n\t" /* loop if k < num_words */ + + /* second half */ + "mov %[k], %[num] \n\t" /* k = num_words; k > 0; --k */ + "add r28, %[num] \n\t" /* move right ptr to point at the end of right */ + "adc r29, %[zero] \n\t" + + "1: \n\t" + "ldi %[i], 0 \n\t" /* i = 0; i < k; ++i */ + + "2: \n\t" + "ld r0, x+ \n\t" + "ld r1, -y \n\t" + "mul r0, r1 \n\t" + + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "inc %[i] \n\t" + "cp %[i], %[k] \n\t" + "brlo 2b \n\t" /* loop if i < k */ + + "add r28, %[k] \n\t" /* fix up right ptr */ + "adc r29, %[zero] \n\t" + + "st z+, %[r0] \n\t" /* Store the result. */ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "dec %[k] \n\t" + "sub r26, %[k] \n\t" /* fix up left ptr (after k is decremented, so next time + we start 1 higher) */ + "sbc r27, %[zero] \n\t" + + "cp %[k], %[zero] \n\t" + "brne 1b \n\t" /* loop if k > 0 */ + + "st z+, %[r0] \n\t" /* Store last result byte. */ + "eor r1, r1 \n\t" /* fix r1 to be 0 again */ + + : "+z" (result), "+x" (left), "+y" (right), + [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), + [zero] "+r" (zero), [num] "+r" (num_words), + [k] "=&r" (k), [i] "=&r" (i) + : + : "r0", "cc" + ); +} +#define asm_mult 1 +#endif + +#if (uECC_SQUARE_FUNC && !asm_square) +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + volatile uECC_word_t *r = result; + uint8_t r0 = 0; + uint8_t r1 = 0; + uint8_t r2 = 0; + uint8_t zero = 0; + uint8_t k; + + __asm__ volatile ( + "ldi %[k], 1 \n\t" /* k = 1; k < num_words * 2; ++k */ + + "1: \n\t" + + "movw r26, %[orig] \n\t" /* copy orig ptr to 'left' ptr */ + "movw r30, %[orig] \n\t" /* copy orig ptr to 'right' ptr */ + "cp %[k], %[num] \n\t" + "brlo 2f \n\t" + "breq 2f \n\t" + + /* when k > num_words, we start from (k - num_words) on the 'left' ptr */ + "add r26, %[k] \n\t" + "adc r27, %[zero] \n\t" + "sub r26, %[num] \n\t" + "sbc r27, %[zero] \n\t" + "add r30, %[num] \n\t" /* move right ptr to point at the end */ + "adc r31, %[zero] \n\t" + "rjmp 3f \n\t" + + "2: \n\t" /* when k <= num_words, we add k to the 'right' ptr */ + "add r30, %[k] \n\t" /* pre-add 'right' ptr */ + "adc r31, %[zero] \n\t" + + "3: \n\t" + "ld r0, x+ \n\t" + "cp r26, r30 \n\t" /* if left == right here, then we are done after this mult + (and we don't need to double) */ + "breq 4f \n\t" + "ld r1, -z \n\t" + "mul r0, r1 \n\t" + + /* add twice since it costs the same as doubling */ + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "cpse r26, r30 \n\t" /* if left == right here, then we are done */ + "rjmp 3b \n\t" + "rjmp 5f \n\t" /* skip code for non-doubled mult */ + + "4: \n\t" + "ld r1, -z \n\t" + "mul r0, r1 \n\t" + "add %[r0], r0 \n\t" + "adc %[r1], r1 \n\t" + "adc %[r2], %[zero] \n\t" + + "5: \n\t" + "movw r30, %[result] \n\t" /* make z point to result */ + "st z+, %[r0] \n\t" /* Store the result. */ + "movw %[result], r30 \n\t" /* update result ptr*/ + "mov %[r0], %[r1] \n\t" + "mov %[r1], %[r2] \n\t" + "mov %[r2], %[zero] \n\t" + + "inc %[k] \n\t" + "cp %[k], %[max] \n\t" + "brlo 1b \n\t" /* loop if k < num_words * 2 */ + + "movw r30, %[result] \n\t" /* make z point to result */ + "st z+, %[r0] \n\t" /* Store last result byte. */ + "eor r1, r1 \n\t" /* fix r1 to be 0 again */ + + : [result] "+r" (r), + [r0] "+r" (r0), [r1] "+r" (r1), [r2] "+r" (r2), [zero] "+r" (zero), + [k] "=&a" (k) + : [orig] "r" (left), [max] "r" ((uint8_t)(2 * num_words)), + [num] "r" (num_words) + : "r0", "r26", "r27", "r30", "r31", "cc" + ); +} +#define asm_square 1 +#endif /* uECC_SQUARE_FUNC && !asm_square */ + +#endif /* _UECC_ASM_AVR_H_ */ diff --git a/core/embed/ble_firmware/uecc/asm_avr_mult_square.inc b/core/embed/ble_firmware/uecc/asm_avr_mult_square.inc new file mode 100644 index 000000000..7ae08bce6 --- /dev/null +++ b/core/embed/ble_firmware/uecc/asm_avr_mult_square.inc @@ -0,0 +1,26311 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_ASM_AVR_MULT_SQUARE_H_ +#define _UECC_ASM_AVR_MULT_SQUARE_H_ + +#define FAST_MULT_ASM_20 \ + "adiw r30, 10 \n\t" \ + "adiw r28, 10 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 30 \n\t" \ + "sbiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" + +#define FAST_MULT_ASM_20_TO_24 \ + "cpi r18, 20 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 24 \n\t" \ + "sbiw r28, 24 \n\t" \ + "sbiw r30, 20 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "st z+, r21 \n\t" \ + "st z+, r19 \n\t" \ + "adiw r26, 4 \n\t" \ + "adiw r28, 4 \n\t" + +#define FAST_MULT_ASM_24 \ + "adiw r30, 20 \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 18 \n\t" \ + "sbiw r28, 14 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 38 \n\t" \ + "sbiw r28, 24 \n\t" \ + "sbiw r26, 14 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" + +#define FAST_MULT_ASM_24_TO_28 \ + "cpi r18, 24 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 28 \n\t" \ + "sbiw r28, 28 \n\t" \ + "sbiw r30, 24 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "st z+, r19 \n\t" \ + "st z+, r20 \n\t" \ + "adiw r26, 4 \n\t" \ + "adiw r28, 4 \n\t" + +#define FAST_MULT_ASM_28 \ + "adiw r30, 20 \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 26 \n\t" \ + "sbiw r28, 18 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r30, 46 \n\t" \ + "sbiw r28, 28 \n\t" \ + "sbiw r26, 18 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" + +#define FAST_MULT_ASM_28_TO_32 \ + "cpi r18, 28 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r6, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r7, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r8, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r9, y+ \n\t" \ + "sbiw r26, 32 \n\t" \ + "sbiw r28, 32 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + \ + "mul r2, r14 \n\t" \ + "mov r19, r0 \n\t" \ + "mov r20, r1 \n\t" \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r10, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "mul r2, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r25 \n\t" \ + "ld r11, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "mul r2, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r25 \n\t" \ + "ld r12, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "mul r2, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "ld r0, z \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r25 \n\t" \ + "ld r13, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "mul r2, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r12, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "ldi r19, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "st z+, r20 \n\t" \ + \ + "ldi r20, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r20, r25 \n\t" \ + "st z+, r21 \n\t" \ + \ + "ldi r21, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r20, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "st z+, r19 \n\t" \ + \ + "mul r5, r9 \n\t" \ + "add r20, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "st z+, r20 \n\t" \ + "st z+, r21 \n\t" + /* Not necessary to move ptrs since we don't support sizes > 32 */ + +#define FAST_MULT_ASM_32 \ + "adiw r30, 30 \n\t" \ + "adiw r28, 30 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r30, 14 \n\t" \ + "sbiw r28, 12 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r21, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r30, 34 \n\t" \ + "sbiw r28, 22 \n\t" \ + "sbiw r26, 12 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r30, 54 \n\t" \ + "sbiw r28, 32 \n\t" \ + "sbiw r26, 22 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r12, y+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r17, y+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r18, y+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r19, y+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r20, y+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r21, y+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r18, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r19, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r20, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r21, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r25 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r19 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r18 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r20 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r19 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r21 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" + +#define FAST_SQUARE_ASM_20 \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + "push r26 \n\t" \ + "push r27 \n\t" \ + "ldi r25, 0 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r4, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r6, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r8, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r10, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r12, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r14, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r16, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r27 \n\t" \ + "adc r24, r26 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r26, 0 \n\t" \ + "mul r18, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r27, r1 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "adc r26, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r27 \n\t" \ + "rol r26 \n\t" \ + "add r23, r24 \n\t" \ + "adc r27, r22 \n\t" \ + "adc r26, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r19, r21 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r27, r0 \n\t" \ + "adc r26, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r20, r20 \n\t" \ + "add r27, r0 \n\t" \ + "adc r26, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r27 \n\t" \ + \ + "ldi r27, 0 \n\t" \ + "mul r20, r21 \n\t" \ + "lsl r0 \n\t" \ + "rol r1 \n\t" \ + "adc r27, r25 \n\t" \ + "add r26, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r27, r25 \n\t" \ + "st z+, r26 \n\t" \ + \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r27, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r27 \n\t" \ + "pop r27 \n\t" \ + "pop r26 \n\t" + +#define FAST_SQUARE_ASM_20_TO_24 \ + "cpi r20, 20 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 24 \n\t" \ + "sbiw r30, 20 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "adc r14, r25 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r16, r0 \n\t" \ + "mov r17, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r18, r0 \n\t" \ + "mov r19, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r21, r0 \n\t" \ + "mov r22, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "add r16, r14 \n\t" \ + "adc r17, r15 \n\t" \ + "adc r18, r25 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r14, r0 \n\t" \ + "mov r15, r1 \n\t" \ + "mov r28, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mov r29, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r15, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mov r10, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mov r12, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + \ + "lsl r14 \n\t" \ + "rol r15 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "adc r24, r25 \n\t" \ + "add r16, r14 \n\t" \ + "adc r17, r15 \n\t" \ + "adc r18, r28 \n\t" \ + "adc r19, r29 \n\t" \ + "adc r21, r10 \n\t" \ + "adc r22, r11 \n\t" \ + "adc r23, r12 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "st z+, r16 \n\t" \ + "st z+, r17 \n\t" \ + "st z+, r18 \n\t" \ + "st z+, r19 \n\t" \ + "st z+, r21 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_24 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r22 \n\t" \ + \ + "sbiw r26, 4 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r5 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r4 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r4, r5 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#define FAST_SQUARE_ASM_24_TO_28 \ + "cpi r20, 24 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 28 \n\t" \ + "sbiw r30, 24 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "adc r18, r25 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r21, r0 \n\t" \ + "mov r22, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r28, r0 \n\t" \ + "mov r29, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "add r21, r18 \n\t" \ + "adc r22, r19 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r18, r0 \n\t" \ + "mov r19, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r19, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mov r14, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mov r16, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + \ + "lsl r18 \n\t" \ + "rol r19 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "adc r11, r25 \n\t" \ + "add r21, r18 \n\t" \ + "adc r22, r19 \n\t" \ + "adc r23, r12 \n\t" \ + "adc r24, r13 \n\t" \ + "adc r28, r14 \n\t" \ + "adc r29, r15 \n\t" \ + "adc r10, r16 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "st z+, r21 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + "st z+, r28 \n\t" \ + "st z+, r29 \n\t" \ + "st z+, r10 \n\t" \ + "st z+, r11 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_28 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r5, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r24 \n\t" \ + \ + "sbiw r26, 8 \n\t" \ + "sbiw r30, 36 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r7, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r8, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r8, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r9, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r9, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r10, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r11, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r13, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r7, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r8, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r8, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#define FAST_SQUARE_ASM_28_TO_32 \ + "cpi r20, 28 \n\t" \ + "brne 1f \n\t" \ + "jmp 2f \n\t" \ + "1: \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "sbiw r26, 32 \n\t" \ + "sbiw r30, 28 \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + \ + "mul r2, r6 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mov r12, r25 \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r28, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r28, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r24, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + \ + "lsl r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "ld r0, z \n\t" \ + "add r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "ld r0, z \n\t" \ + "adc r23, r0 \n\t" \ + "st z+, r23 \n\t" \ + "ld r0, z \n\t" \ + "adc r24, r0 \n\t" \ + "st z+, r24 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "bst r28, 0 \n\t" \ + "lsr r29 \n\t" \ + "ror r28 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r10, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r10, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r11, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r29, r0 \n\t" \ + "adc r10, r1 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r12, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r10, r0 \n\t" \ + "adc r11, r1 \n\t" \ + "adc r12, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r13, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r11, r0 \n\t" \ + "adc r12, r1 \n\t" \ + "adc r13, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r14, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r12, r0 \n\t" \ + "adc r13, r1 \n\t" \ + "adc r14, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r15, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r13, r0 \n\t" \ + "adc r14, r1 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r16, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r14, r0 \n\t" \ + "adc r15, r1 \n\t" \ + "adc r16, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r17, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r15, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r18, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "mov r21, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "mov r22, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + "adc r22, r25 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "mov r23, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r21, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "mov r24, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "lsl r28 \n\t" \ + "bld r28, 0 \n\t" \ + "rol r29 \n\t" \ + "rol r10 \n\t" \ + "rol r11 \n\t" \ + "rol r12 \n\t" \ + "rol r13 \n\t" \ + "rol r14 \n\t" \ + "rol r15 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "rol r22 \n\t" \ + "rol r23 \n\t" \ + "rol r24 \n\t" \ + "ld r0, z \n\t" \ + "add r28, r0 \n\t" \ + "st z+, r28 \n\t" \ + "ld r0, z \n\t" \ + "adc r29, r0 \n\t" \ + "st z+, r29 \n\t" \ + "ld r0, z \n\t" \ + "adc r10, r0 \n\t" \ + "st z+, r10 \n\t" \ + "ld r0, z \n\t" \ + "adc r11, r0 \n\t" \ + "st z+, r11 \n\t" \ + "ld r0, z \n\t" \ + "adc r12, r0 \n\t" \ + "st z+, r12 \n\t" \ + "ld r0, z \n\t" \ + "adc r13, r0 \n\t" \ + "st z+, r13 \n\t" \ + "ld r0, z \n\t" \ + "adc r14, r0 \n\t" \ + "st z+, r14 \n\t" \ + "ld r0, z \n\t" \ + "adc r15, r0 \n\t" \ + "st z+, r15 \n\t" \ + "ld r0, z \n\t" \ + "adc r16, r0 \n\t" \ + "st z+, r16 \n\t" \ + "ld r0, z \n\t" \ + "adc r17, r0 \n\t" \ + "st z+, r17 \n\t" \ + "ld r0, z \n\t" \ + "adc r18, r0 \n\t" \ + "st z+, r18 \n\t" \ + "ld r0, z \n\t" \ + "adc r19, r0 \n\t" \ + "st z+, r19 \n\t" \ + "ld r0, z \n\t" \ + "adc r21, r0 \n\t" \ + "st z+, r21 \n\t" \ + "ld r0, z \n\t" \ + "adc r22, r0 \n\t" \ + "st z+, r22 \n\t" \ + "adc r23, r25 \n\t" \ + "adc r24, r25 \n\t" \ + \ + "mul r2, r2 \n\t" \ + "mov r28, r0 \n\t" \ + "mov r29, r1 \n\t" \ + "mul r3, r3 \n\t" \ + "mov r10, r0 \n\t" \ + "mov r11, r1 \n\t" \ + "mul r4, r4 \n\t" \ + "mov r12, r0 \n\t" \ + "mov r13, r1 \n\t" \ + "mul r5, r5 \n\t" \ + "mov r14, r0 \n\t" \ + "mov r15, r1 \n\t" \ + "add r28, r23 \n\t" \ + "adc r29, r24 \n\t" \ + "adc r10, r25 \n\t" \ + "adc r11, r25 \n\t" \ + \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mov r16, r25 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r16, r25 \n\t" \ + "mov r17, r25 \n\t" \ + "mul r8, r5 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r24, r0 \n\t" \ + "adc r16, r1 \n\t" \ + "adc r17, r25 \n\t" \ + "mov r18, r25 \n\t" \ + "mul r9, r5 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r16, r0 \n\t" \ + "adc r17, r1 \n\t" \ + "adc r18, r25 \n\t" \ + "mov r19, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r17, r0 \n\t" \ + "adc r18, r1 \n\t" \ + "adc r19, r25 \n\t" \ + "mov r21, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r18, r0 \n\t" \ + "adc r19, r1 \n\t" \ + "adc r21, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r19, r0 \n\t" \ + "adc r21, r1 \n\t" \ + \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r16 \n\t" \ + "rol r17 \n\t" \ + "rol r18 \n\t" \ + "rol r19 \n\t" \ + "rol r21 \n\t" \ + "adc r15, r25 \n\t" \ + "add r28, r23 \n\t" \ + "adc r29, r24 \n\t" \ + "adc r10, r16 \n\t" \ + "adc r11, r17 \n\t" \ + "adc r12, r18 \n\t" \ + "adc r13, r19 \n\t" \ + "adc r14, r21 \n\t" \ + "adc r15, r25 \n\t" \ + \ + "st z+, r28 \n\t" \ + "st z+, r29 \n\t" \ + "st z+, r10 \n\t" \ + "st z+, r11 \n\t" \ + "st z+, r12 \n\t" \ + "st z+, r13 \n\t" \ + "st z+, r14 \n\t" \ + "st z+, r15 \n\t" \ + "adiw r26, 4 \n\t" + +#define FAST_SQUARE_ASM_32 \ + "ldi r25, 0 \n\t" \ + "movw r28, r26 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "adiw r28, 20 \n\t" \ + "ld r12, y+ \n\t" \ + "ld r13, y+ \n\t" \ + "ld r14, y+ \n\t" \ + "ld r15, y+ \n\t" \ + "ld r16, y+ \n\t" \ + "ld r17, y+ \n\t" \ + "adiw r30, 20 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul 2, 12 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r13, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r14, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r15, y+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r16, y+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r17, y+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r12 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r13 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r23, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r2, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r3, r14 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r24, 0 \n\t" \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r2, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r3, r15 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r3, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r4, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r6, r17 \n\t" \ + "add r24, r0 \n\t" \ + "adc r22, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r24 \n\t" \ + \ + "mul r7, r17 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "st z+, r22 \n\t" \ + "st z+, r23 \n\t" \ + \ + "sbiw r26, 12 \n\t" \ + "sbiw r30, 44 \n\t" \ + "ld r2, x+ \n\t" \ + "ld r3, x+ \n\t" \ + "ld r4, x+ \n\t" \ + "ld r5, x+ \n\t" \ + "ld r6, x+ \n\t" \ + "ld r7, x+ \n\t" \ + "ld r8, x+ \n\t" \ + "ld r9, x+ \n\t" \ + "ld r10, x+ \n\t" \ + "ld r11, x+ \n\t" \ + "ld r12, x+ \n\t" \ + "ld r13, x+ \n\t" \ + "ld r14, x+ \n\t" \ + "ld r15, x+ \n\t" \ + "ld r16, x+ \n\t" \ + "ld r17, x+ \n\t" \ + "ld r18, x+ \n\t" \ + "ld r19, x+ \n\t" \ + "ld r20, x+ \n\t" \ + "ld r21, x+ \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r2, r2 \n\t" \ + "st z+, r0 \n\t" \ + "mov r22, r1 \n\t" \ + \ + "ldi r24, 0 \n\t" \ + "mul r2, r3 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "add r22, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r24, r25 \n\t" \ + "st z+, r22 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r14 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r15 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r16 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r17 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r18 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r19 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r2, r20 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r3, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r2, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r3, r21 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r12, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r3, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r4, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r3, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r4, r2 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r5, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r4, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r5, r3 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r14, r14 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r5, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r6, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r5, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r6, r4 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r7, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r15, r15 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r6, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r7, r5 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r16, r16 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r7, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r8, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r7, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r8, r6 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r9, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r10, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r17, r17 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r8, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r9, r7 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r11, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r18, r18 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r9, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r10, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r11, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r9, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r10, r8 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r11, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r12, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r19, r19 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r12, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r10, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r11, r9 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r12, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r13, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r20, r20 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r11, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r12, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r13, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r11, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r12, r10 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r13, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r14, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r21, r21 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r12, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r13, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r14, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r12, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r13, r11 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r14, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r15, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r2, r2 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r13, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r14, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r15, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ld r13, x+ \n\t" \ + "ldi r22, 0 \n\t" \ + "mul r14, r12 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r15, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r16, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r25 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r3, r3 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r14, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r15, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r16, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r17, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "ld r0, z \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r25 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r15, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r16, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r17, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r18, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r4, r4 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r16, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r17, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r18, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r19, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r17, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r18, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r19, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r20, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r5, r5 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r18, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r19, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r20, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r21, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r19, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r20, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r21, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r2, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r6, r6 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r20, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r21, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r2, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r3, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r21, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r2, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r3, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r4, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r7, r7 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r2, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r3, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r4, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r5, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r3, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r4, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r5, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r6, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r8, r8 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r4, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r5, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r6, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r7, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r5, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r6, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r7, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r8, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r9, r9 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r6, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r7, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r8, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r9, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r7, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r8, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "mul r9, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r10, r10 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r8, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r9, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "mul r10, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r22, 0 \n\t" \ + "mul r9, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r24, r1 \n\t" \ + "mul r10, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r24 \n\t" \ + "rol r22 \n\t" \ + "mul r11, r11 \n\t" \ + "add r23, r0 \n\t" \ + "adc r24, r1 \n\t" \ + "adc r22, r25 \n\t" \ + "add r23, r28 \n\t" \ + "adc r24, r29 \n\t" \ + "adc r22, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r29, 0 \n\t" \ + "mul r10, r13 \n\t" \ + "mov r23, r0 \n\t" \ + "mov r28, r1 \n\t" \ + "mul r11, r12 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "adc r29, r25 \n\t" \ + "lsl r23 \n\t" \ + "rol r28 \n\t" \ + "rol r29 \n\t" \ + "add r23, r24 \n\t" \ + "adc r28, r22 \n\t" \ + "adc r29, r25 \n\t" \ + "st z+, r23 \n\t" \ + \ + "ldi r23, 0 \n\t" \ + "mul r11, r13 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "mul r12, r12 \n\t" \ + "add r28, r0 \n\t" \ + "adc r29, r1 \n\t" \ + "adc r23, r25 \n\t" \ + "st z+, r28 \n\t" \ + \ + "ldi r28, 0 \n\t" \ + "mul r12, r13 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "add r29, r0 \n\t" \ + "adc r23, r1 \n\t" \ + "adc r28, r25 \n\t" \ + "st z+, r29 \n\t" \ + \ + "mul r13, r13 \n\t" \ + "add r23, r0 \n\t" \ + "adc r28, r1 \n\t" \ + "st z+, r23 \n\t" \ + "st z+, r28 \n\t" + +#endif /* _UECC_ASM_AVR_MULT_SQUARE_H_ */ diff --git a/core/embed/ble_firmware/uecc/curve-specific.inc b/core/embed/ble_firmware/uecc/curve-specific.inc new file mode 100644 index 000000000..0453b212c --- /dev/null +++ b/core/embed/ble_firmware/uecc/curve-specific.inc @@ -0,0 +1,1248 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_CURVE_SPECIFIC_H_ +#define _UECC_CURVE_SPECIFIC_H_ + +#define num_bytes_secp160r1 20 +#define num_bytes_secp192r1 24 +#define num_bytes_secp224r1 28 +#define num_bytes_secp256r1 32 +#define num_bytes_secp256k1 32 + +#if (uECC_WORD_SIZE == 1) + +#define num_words_secp160r1 20 +#define num_words_secp192r1 24 +#define num_words_secp224r1 28 +#define num_words_secp256r1 32 +#define num_words_secp256k1 32 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) \ + 0x##a, 0x##b, 0x##c, 0x##d, 0x##e, 0x##f, 0x##g, 0x##h +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##a, 0x##b, 0x##c, 0x##d + +#elif (uECC_WORD_SIZE == 4) + +#define num_words_secp160r1 5 +#define num_words_secp192r1 6 +#define num_words_secp224r1 7 +#define num_words_secp256r1 8 +#define num_words_secp256k1 8 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a + +#elif (uECC_WORD_SIZE == 8) + +#define num_words_secp160r1 3 +#define num_words_secp192r1 3 +#define num_words_secp224r1 4 +#define num_words_secp256r1 4 +#define num_words_secp256k1 4 + +#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##h##g##f##e##d##c##b##a##ull +#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a##ull + +#endif /* uECC_WORD_SIZE */ + +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp224r1 || uECC_SUPPORTS_secp256r1 +static void double_jacobian_default(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[uECC_MAX_WORDS]; + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + if (uECC_vli_isZero(Z1, num_words)) { + return; + } + + uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */ + uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */ + uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */ + uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */ + + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */ + uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */ + uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */ + uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */ + + uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */ + uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */ + if (uECC_vli_testBit(X1, 0)) { + uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words); + uECC_vli_rshift1(X1, num_words); + X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(X1, num_words); + } + /* t1 = 3/2*(x1^2 - z1^4) = B */ + + uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */ + uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */ + uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */ + uECC_vli_modSub(t4, X1, t4, curve->p, num_words); /* t4 = B * (A - x3) - y1^4 = y3 */ + + uECC_vli_set(X1, Z1, num_words); + uECC_vli_set(Z1, Y1, num_words); + uECC_vli_set(Y1, t4, num_words); +} + +/* Computes result = x^3 + ax + b. result must not overlap x. */ +static void x_side_default(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { + uECC_word_t _3[uECC_MAX_WORDS] = {3}; /* -a = 3 */ + wordcount_t num_words = curve->num_words; + + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words); /* r = x^3 - 3x + b */ +} +#endif /* uECC_SUPPORTS_secp... */ + +#if uECC_SUPPORT_COMPRESSED_POINT +#if uECC_SUPPORTS_secp160r1 || uECC_SUPPORTS_secp192r1 || \ + uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1 +/* Compute a = sqrt(a) (mod curve_p). */ +static void mod_sqrt_default(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t p1[uECC_MAX_WORDS] = {1}; + uECC_word_t l_result[uECC_MAX_WORDS] = {1}; + wordcount_t num_words = curve->num_words; + + /* When curve->p == 3 (mod 4), we can compute + sqrt(a) = a^((curve->p + 1) / 4) (mod curve->p). */ + uECC_vli_add(p1, curve->p, p1, num_words); /* p1 = curve_p + 1 */ + for (i = uECC_vli_numBits(p1, num_words) - 1; i > 1; --i) { + uECC_vli_modSquare_fast(l_result, l_result, curve); + if (uECC_vli_testBit(p1, i)) { + uECC_vli_modMult_fast(l_result, l_result, a, curve); + } + } + uECC_vli_set(a, l_result, num_words); +} +#endif /* uECC_SUPPORTS_secp... */ +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +#if uECC_SUPPORTS_secp160r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp160r1 = { + num_words_secp160r1, + num_bytes_secp160r1, + 161, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, 7F, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(57, 22, 75, CA, D3, AE, 27, F9), + BYTES_TO_WORDS_8(C8, F4, 01, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 01, 00, 00, 00) }, + { BYTES_TO_WORDS_8(82, FC, CB, 13, B9, 8B, C3, 68), + BYTES_TO_WORDS_8(89, 69, 64, 46, 28, 73, F5, 8E), + BYTES_TO_WORDS_4(68, B5, 96, 4A), + + BYTES_TO_WORDS_8(32, FB, C5, 7A, 37, 51, 23, 04), + BYTES_TO_WORDS_8(12, C9, DC, 59, 7D, 94, 68, 31), + BYTES_TO_WORDS_4(55, 28, A6, 23) }, + { BYTES_TO_WORDS_8(45, FA, 65, C5, AD, D4, D4, 81), + BYTES_TO_WORDS_8(9F, F8, AC, 65, 8B, 7A, BD, 54), + BYTES_TO_WORDS_4(FC, BE, 97, 1C) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp160r1 +#endif +}; + +uECC_Curve uECC_secp160r1(void) { return &curve_secp160r1; } + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) +/* Computes result = product % curve_p + see http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf page 354 + + Note that this only works if log2(omega) < log2(p) / 2 */ +static void omega_mult_secp160r1(uECC_word_t *result, const uECC_word_t *right); +#if uECC_WORD_SIZE == 8 +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp160r1]; + uECC_word_t copy; + + uECC_vli_clear(tmp, num_words_secp160r1); + uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); + + omega_mult_secp160r1(tmp, product + num_words_secp160r1 - 1); /* (Rq, q) = q * c */ + + product[num_words_secp160r1 - 1] &= 0xffffffff; + copy = tmp[num_words_secp160r1 - 1]; + tmp[num_words_secp160r1 - 1] &= 0xffffffff; + uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp160r1); + tmp[num_words_secp160r1 - 1] = copy; + omega_mult_secp160r1(product, tmp + num_words_secp160r1 - 1); /* Rq*c */ + uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ + + while (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } +} + +static void omega_mult_secp160r1(uint64_t *result, const uint64_t *right) { + uint32_t carry; + unsigned i; + + /* Multiply by (2^31 + 1). */ + carry = 0; + for (i = 0; i < num_words_secp160r1; ++i) { + uint64_t tmp = (right[i] >> 32) | (right[i + 1] << 32); + result[i] = (tmp << 31) + tmp + carry; + carry = (tmp >> 33) + (result[i] < tmp || (carry && result[i] == tmp)); + } + result[i] = carry; +} +#else +static void vli_mmod_fast_secp160r1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp160r1]; + uECC_word_t carry; + + uECC_vli_clear(tmp, num_words_secp160r1); + uECC_vli_clear(tmp + num_words_secp160r1, num_words_secp160r1); + + omega_mult_secp160r1(tmp, product + num_words_secp160r1); /* (Rq, q) = q * c */ + + carry = uECC_vli_add(result, product, tmp, num_words_secp160r1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp160r1); + omega_mult_secp160r1(product, tmp + num_words_secp160r1); /* Rq*c */ + carry += uECC_vli_add(result, result, product, num_words_secp160r1); /* (C1, r) = r + Rq*c */ + + while (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } + if (uECC_vli_cmp_unsafe(result, curve_secp160r1.p, num_words_secp160r1) > 0) { + uECC_vli_sub(result, result, curve_secp160r1.p, num_words_secp160r1); + } +} +#endif + +#if uECC_WORD_SIZE == 1 +static void omega_mult_secp160r1(uint8_t *result, const uint8_t *right) { + uint8_t carry; + uint8_t i; + + /* Multiply by (2^31 + 1). */ + uECC_vli_set(result + 4, right, num_words_secp160r1); /* 2^32 */ + uECC_vli_rshift1(result + 4, num_words_secp160r1); /* 2^31 */ + result[3] = right[0] << 7; /* get last bit from shift */ + + carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ + for (i = num_words_secp160r1; carry; ++i) { + uint16_t sum = (uint16_t)result[i] + carry; + result[i] = (uint8_t)sum; + carry = sum >> 8; + } +} +#elif uECC_WORD_SIZE == 4 +static void omega_mult_secp160r1(uint32_t *result, const uint32_t *right) { + uint32_t carry; + unsigned i; + + /* Multiply by (2^31 + 1). */ + uECC_vli_set(result + 1, right, num_words_secp160r1); /* 2^32 */ + uECC_vli_rshift1(result + 1, num_words_secp160r1); /* 2^31 */ + result[0] = right[0] << 31; /* get last bit from shift */ + + carry = uECC_vli_add(result, result, right, num_words_secp160r1); /* 2^31 + 1 */ + for (i = num_words_secp160r1; carry; ++i) { + uint64_t sum = (uint64_t)result[i] + carry; + result[i] = (uint32_t)sum; + carry = sum >> 32; + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp160r1) */ + +#endif /* uECC_SUPPORTS_secp160r1 */ + +#if uECC_SUPPORTS_secp192r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp192r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp192r1 = { + num_words_secp192r1, + num_bytes_secp192r1, + 192, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(31, 28, D2, B4, B1, C9, 6B, 14), + BYTES_TO_WORDS_8(36, F8, DE, 99, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(12, 10, FF, 82, FD, 0A, FF, F4), + BYTES_TO_WORDS_8(00, 88, A1, 43, EB, 20, BF, 7C), + BYTES_TO_WORDS_8(F6, 90, 30, B0, 0E, A8, 8D, 18), + + BYTES_TO_WORDS_8(11, 48, 79, 1E, A1, 77, F9, 73), + BYTES_TO_WORDS_8(D5, CD, 24, 6B, ED, 11, 10, 63), + BYTES_TO_WORDS_8(78, DA, C8, FF, 95, 2B, 19, 07) }, + { BYTES_TO_WORDS_8(B1, B9, 46, C1, EC, DE, B8, FE), + BYTES_TO_WORDS_8(49, 30, 24, 72, AB, E9, A7, 0F), + BYTES_TO_WORDS_8(E7, 80, 9C, E5, 19, 05, 21, 64) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp192r1 +#endif +}; + +uECC_Curve uECC_secp192r1(void) { return &curve_secp192r1; } + +#if (uECC_OPTIMIZATION_LEVEL > 0) +/* Computes result = product % curve_p. + See algorithm 5 and 6 from http://www.isys.uni-klu.ac.at/PDF/2001-0126-MT.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp192r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp192r1]; + uint8_t carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[24], num_words_secp192r1); + carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = tmp[2] = tmp[3] = tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = product[24]; tmp[9] = product[25]; tmp[10] = product[26]; tmp[11] = product[27]; + tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; + tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; + tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[8] = product[40]; + tmp[1] = tmp[9] = product[41]; + tmp[2] = tmp[10] = product[42]; + tmp[3] = tmp[11] = product[43]; + tmp[4] = tmp[12] = product[44]; + tmp[5] = tmp[13] = product[45]; + tmp[6] = tmp[14] = product[46]; + tmp[7] = tmp[15] = product[47]; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp192r1(uint32_t *result, uint32_t *product) { + uint32_t tmp[num_words_secp192r1]; + int carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[6], num_words_secp192r1); + carry = uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = 0; + tmp[2] = product[6]; + tmp[3] = product[7]; + tmp[4] = product[8]; + tmp[5] = product[9]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[2] = product[10]; + tmp[1] = tmp[3] = product[11]; + tmp[4] = tmp[5] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#else +static void vli_mmod_fast_secp192r1(uint64_t *result, uint64_t *product) { + uint64_t tmp[num_words_secp192r1]; + int carry; + + uECC_vli_set(result, product, num_words_secp192r1); + + uECC_vli_set(tmp, &product[3], num_words_secp192r1); + carry = (int)uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = 0; + tmp[1] = product[3]; + tmp[2] = product[4]; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + tmp[0] = tmp[1] = product[5]; + tmp[2] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp192r1); + + while (carry || uECC_vli_cmp_unsafe(curve_secp192r1.p, result, num_words_secp192r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp192r1.p, num_words_secp192r1); + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ + +#endif /* uECC_SUPPORTS_secp192r1 */ + +#if uECC_SUPPORTS_secp224r1 + +#if uECC_SUPPORT_COMPRESSED_POINT +static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve); +#endif +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp224r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp224r1 = { + num_words_secp224r1, + num_bytes_secp224r1, + 224, /* num_n_bits */ + { BYTES_TO_WORDS_8(01, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(3D, 2A, 5C, 5C, 45, 29, DD, 13), + BYTES_TO_WORDS_8(3E, F0, B8, E0, A2, 16, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_4(FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(21, 1D, 5C, 11, D6, 80, 32, 34), + BYTES_TO_WORDS_8(22, 11, C2, 56, D3, C1, 03, 4A), + BYTES_TO_WORDS_8(B9, 90, 13, 32, 7F, BF, B4, 6B), + BYTES_TO_WORDS_4(BD, 0C, 0E, B7), + + BYTES_TO_WORDS_8(34, 7E, 00, 85, 99, 81, D5, 44), + BYTES_TO_WORDS_8(64, 47, 07, 5A, A0, 75, 43, CD), + BYTES_TO_WORDS_8(E6, DF, 22, 4C, FB, 23, F7, B5), + BYTES_TO_WORDS_4(88, 63, 37, BD) }, + { BYTES_TO_WORDS_8(B4, FF, 55, 23, 43, 39, 0B, 27), + BYTES_TO_WORDS_8(BA, D8, BF, D7, B7, B0, 44, 50), + BYTES_TO_WORDS_8(56, 32, 41, F5, AB, B3, 04, 0C), + BYTES_TO_WORDS_4(85, 0A, 05, B4) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_secp224r1, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp224r1 +#endif +}; + +uECC_Curve uECC_secp224r1(void) { return &curve_secp224r1; } + + +#if uECC_SUPPORT_COMPRESSED_POINT +/* Routine 3.2.4 RS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rs(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *f0) { + uECC_word_t t[num_words_secp224r1]; + + uECC_vli_modSquare_fast(t, d0, &curve_secp224r1); /* t <-- d0 ^ 2 */ + uECC_vli_modMult_fast(e1, d0, e0, &curve_secp224r1); /* e1 <-- d0 * e0 */ + uECC_vli_modAdd(d1, t, f0, curve_secp224r1.p, num_words_secp224r1); /* d1 <-- t + f0 */ + uECC_vli_modAdd(e1, e1, e1, curve_secp224r1.p, num_words_secp224r1); /* e1 <-- e1 + e1 */ + uECC_vli_modMult_fast(f1, t, f0, &curve_secp224r1); /* f1 <-- t * f0 */ + uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ + uECC_vli_modAdd(f1, f1, f1, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- f1 + f1 */ +} + +/* Routine 3.2.5 RSS; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rss(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *f0, + const bitcount_t j) { + bitcount_t i; + + uECC_vli_set(d1, d0, num_words_secp224r1); /* d1 <-- d0 */ + uECC_vli_set(e1, e0, num_words_secp224r1); /* e1 <-- e0 */ + uECC_vli_set(f1, f0, num_words_secp224r1); /* f1 <-- f0 */ + for (i = 1; i <= j; i++) { + mod_sqrt_secp224r1_rs(d1, e1, f1, d1, e1, f1); /* RS (d1,e1,f1,d1,e1,f1) */ + } +} + +/* Routine 3.2.6 RM; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rm(uECC_word_t *d2, + uECC_word_t *e2, + uECC_word_t *f2, + const uECC_word_t *c, + const uECC_word_t *d0, + const uECC_word_t *e0, + const uECC_word_t *d1, + const uECC_word_t *e1) { + uECC_word_t t1[num_words_secp224r1]; + uECC_word_t t2[num_words_secp224r1]; + + uECC_vli_modMult_fast(t1, e0, e1, &curve_secp224r1); /* t1 <-- e0 * e1 */ + uECC_vli_modMult_fast(t1, t1, c, &curve_secp224r1); /* t1 <-- t1 * c */ + /* t1 <-- p - t1 */ + uECC_vli_modSub(t1, curve_secp224r1.p, t1, curve_secp224r1.p, num_words_secp224r1); + uECC_vli_modMult_fast(t2, d0, d1, &curve_secp224r1); /* t2 <-- d0 * d1 */ + uECC_vli_modAdd(t2, t2, t1, curve_secp224r1.p, num_words_secp224r1); /* t2 <-- t2 + t1 */ + uECC_vli_modMult_fast(t1, d0, e1, &curve_secp224r1); /* t1 <-- d0 * e1 */ + uECC_vli_modMult_fast(e2, d1, e0, &curve_secp224r1); /* e2 <-- d1 * e0 */ + uECC_vli_modAdd(e2, e2, t1, curve_secp224r1.p, num_words_secp224r1); /* e2 <-- e2 + t1 */ + uECC_vli_modSquare_fast(f2, e2, &curve_secp224r1); /* f2 <-- e2^2 */ + uECC_vli_modMult_fast(f2, f2, c, &curve_secp224r1); /* f2 <-- f2 * c */ + /* f2 <-- p - f2 */ + uECC_vli_modSub(f2, curve_secp224r1.p, f2, curve_secp224r1.p, num_words_secp224r1); + uECC_vli_set(d2, t2, num_words_secp224r1); /* d2 <-- t2 */ +} + +/* Routine 3.2.7 RP; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1_rp(uECC_word_t *d1, + uECC_word_t *e1, + uECC_word_t *f1, + const uECC_word_t *c, + const uECC_word_t *r) { + wordcount_t i; + wordcount_t pow2i = 1; + uECC_word_t d0[num_words_secp224r1]; + uECC_word_t e0[num_words_secp224r1] = {1}; /* e0 <-- 1 */ + uECC_word_t f0[num_words_secp224r1]; + + uECC_vli_set(d0, r, num_words_secp224r1); /* d0 <-- r */ + /* f0 <-- p - c */ + uECC_vli_modSub(f0, curve_secp224r1.p, c, curve_secp224r1.p, num_words_secp224r1); + for (i = 0; i <= 6; i++) { + mod_sqrt_secp224r1_rss(d1, e1, f1, d0, e0, f0, pow2i); /* RSS (d1,e1,f1,d0,e0,f0,2^i) */ + mod_sqrt_secp224r1_rm(d1, e1, f1, c, d1, e1, d0, e0); /* RM (d1,e1,f1,c,d1,e1,d0,e0) */ + uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ + uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ + uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ + pow2i *= 2; + } +} + +/* Compute a = sqrt(a) (mod curve_p). */ +/* Routine 3.2.8 mp_mod_sqrt_224; from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +static void mod_sqrt_secp224r1(uECC_word_t *a, uECC_Curve curve) { + bitcount_t i; + uECC_word_t e1[num_words_secp224r1]; + uECC_word_t f1[num_words_secp224r1]; + uECC_word_t d0[num_words_secp224r1]; + uECC_word_t e0[num_words_secp224r1]; + uECC_word_t f0[num_words_secp224r1]; + uECC_word_t d1[num_words_secp224r1]; + + /* s = a; using constant instead of random value */ + mod_sqrt_secp224r1_rp(d0, e0, f0, a, a); /* RP (d0, e0, f0, c, s) */ + mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ + for (i = 1; i <= 95; i++) { + uECC_vli_set(d0, d1, num_words_secp224r1); /* d0 <-- d1 */ + uECC_vli_set(e0, e1, num_words_secp224r1); /* e0 <-- e1 */ + uECC_vli_set(f0, f1, num_words_secp224r1); /* f0 <-- f1 */ + mod_sqrt_secp224r1_rs(d1, e1, f1, d0, e0, f0); /* RS (d1, e1, f1, d0, e0, f0) */ + if (uECC_vli_isZero(d1, num_words_secp224r1)) { /* if d1 == 0 */ + break; + } + } + uECC_vli_modInv(f1, e0, curve_secp224r1.p, num_words_secp224r1); /* f1 <-- 1 / e0 */ + uECC_vli_modMult_fast(a, d0, f1, &curve_secp224r1); /* a <-- d0 / e0 */ +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +#if (uECC_OPTIMIZATION_LEVEL > 0) +/* Computes result = product % curve_p + from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp224r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp224r1]; + int8_t carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[28]; tmp[13] = product[29]; tmp[14] = product[30]; tmp[15] = product[31]; + tmp[16] = product[32]; tmp[17] = product[33]; tmp[18] = product[34]; tmp[19] = product[35]; + tmp[20] = product[36]; tmp[21] = product[37]; tmp[22] = product[38]; tmp[23] = product[39]; + tmp[24] = product[40]; tmp[25] = product[41]; tmp[26] = product[42]; tmp[27] = product[43]; + carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; + tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; + tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = product[28]; tmp[1] = product[29]; tmp[2] = product[30]; tmp[3] = product[31]; + tmp[4] = product[32]; tmp[5] = product[33]; tmp[6] = product[34]; tmp[7] = product[35]; + tmp[8] = product[36]; tmp[9] = product[37]; tmp[10] = product[38]; tmp[11] = product[39]; + tmp[12] = product[40]; tmp[13] = product[41]; tmp[14] = product[42]; tmp[15] = product[43]; + tmp[16] = product[44]; tmp[17] = product[45]; tmp[18] = product[46]; tmp[19] = product[47]; + tmp[20] = product[48]; tmp[21] = product[49]; tmp[22] = product[50]; tmp[23] = product[51]; + tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; + tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; + tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp224r1(uint32_t *result, uint32_t *product) +{ + uint32_t tmp[num_words_secp224r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[7]; + tmp[4] = product[8]; + tmp[5] = product[9]; + tmp[6] = product[10]; + carry = uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = 0; + carry += uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = product[7]; + tmp[1] = product[8]; + tmp[2] = product[9]; + tmp[3] = product[10]; + tmp[4] = product[11]; + tmp[5] = product[12]; + tmp[6] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = tmp[6] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#else +static void vli_mmod_fast_secp224r1(uint64_t *result, uint64_t *product) +{ + uint64_t tmp[num_words_secp224r1]; + int carry = 0; + + /* t */ + uECC_vli_set(result, product, num_words_secp224r1); + result[num_words_secp224r1 - 1] &= 0xffffffff; + + /* s1 */ + tmp[0] = 0; + tmp[1] = product[3] & 0xffffffff00000000ull; + tmp[2] = product[4]; + tmp[3] = product[5] & 0xffffffff; + uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* s2 */ + tmp[1] = product[5] & 0xffffffff00000000ull; + tmp[2] = product[6]; + tmp[3] = 0; + uECC_vli_add(result, result, tmp, num_words_secp224r1); + + /* d1 */ + tmp[0] = (product[3] >> 32) | (product[4] << 32); + tmp[1] = (product[4] >> 32) | (product[5] << 32); + tmp[2] = (product[5] >> 32) | (product[6] << 32); + tmp[3] = product[6] >> 32; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + /* d2 */ + tmp[0] = (product[5] >> 32) | (product[6] << 32); + tmp[1] = product[6] >> 32; + tmp[2] = tmp[3] = 0; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp224r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp224r1.p, num_words_secp224r1); + } while (carry < 0); + } else { + while (uECC_vli_cmp_unsafe(curve_secp224r1.p, result, num_words_secp224r1) != 1) { + uECC_vli_sub(result, result, curve_secp224r1.p, num_words_secp224r1); + } + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0) */ + +#endif /* uECC_SUPPORTS_secp224r1 */ + +#if uECC_SUPPORTS_secp256r1 + +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp256r1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp256r1 = { + num_words_secp256r1, + num_bytes_secp256r1, + 256, /* num_n_bits */ + { BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3), + BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4), + BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77), + BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8), + BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B), + + BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB), + BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B), + BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E), + BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F) }, + { BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B), + BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65), + BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3), + BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A) }, + &double_jacobian_default, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_default, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp256r1 +#endif +}; + +uECC_Curve uECC_secp256r1(void) { return &curve_secp256r1; } + + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) +/* Computes result = product % curve_p + from http://www.nsa.gov/ia/_files/nist-routines.pdf */ +#if uECC_WORD_SIZE == 1 +static void vli_mmod_fast_secp256r1(uint8_t *result, uint8_t *product) { + uint8_t tmp[num_words_secp256r1]; + int8_t carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0; + tmp[4] = tmp[5] = tmp[6] = tmp[7] = 0; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[44]; tmp[13] = product[45]; tmp[14] = product[46]; tmp[15] = product[47]; + tmp[16] = product[48]; tmp[17] = product[49]; tmp[18] = product[50]; tmp[19] = product[51]; + tmp[20] = product[52]; tmp[21] = product[53]; tmp[22] = product[54]; tmp[23] = product[55]; + tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; + tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; + carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[12] = product[48]; tmp[13] = product[49]; tmp[14] = product[50]; tmp[15] = product[51]; + tmp[16] = product[52]; tmp[17] = product[53]; tmp[18] = product[54]; tmp[19] = product[55]; + tmp[20] = product[56]; tmp[21] = product[57]; tmp[22] = product[58]; tmp[23] = product[59]; + tmp[24] = product[60]; tmp[25] = product[61]; tmp[26] = product[62]; tmp[27] = product[63]; + tmp[28] = tmp[29] = tmp[30] = tmp[31] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[32]; tmp[1] = product[33]; tmp[2] = product[34]; tmp[3] = product[35]; + tmp[4] = product[36]; tmp[5] = product[37]; tmp[6] = product[38]; tmp[7] = product[39]; + tmp[8] = product[40]; tmp[9] = product[41]; tmp[10] = product[42]; tmp[11] = product[43]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[56]; tmp[25] = product[57]; tmp[26] = product[58]; tmp[27] = product[59]; + tmp[28] = product[60]; tmp[29] = product[61]; tmp[30] = product[62]; tmp[31] = product[63]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = product[36]; tmp[1] = product[37]; tmp[2] = product[38]; tmp[3] = product[39]; + tmp[4] = product[40]; tmp[5] = product[41]; tmp[6] = product[42]; tmp[7] = product[43]; + tmp[8] = product[44]; tmp[9] = product[45]; tmp[10] = product[46]; tmp[11] = product[47]; + tmp[12] = product[52]; tmp[13] = product[53]; tmp[14] = product[54]; tmp[15] = product[55]; + tmp[16] = product[56]; tmp[17] = product[57]; tmp[18] = product[58]; tmp[19] = product[59]; + tmp[20] = product[60]; tmp[21] = product[61]; tmp[22] = product[62]; tmp[23] = product[63]; + tmp[24] = product[52]; tmp[25] = product[53]; tmp[26] = product[54]; tmp[27] = product[55]; + tmp[28] = product[32]; tmp[29] = product[33]; tmp[30] = product[34]; tmp[31] = product[35]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = product[44]; tmp[1] = product[45]; tmp[2] = product[46]; tmp[3] = product[47]; + tmp[4] = product[48]; tmp[5] = product[49]; tmp[6] = product[50]; tmp[7] = product[51]; + tmp[8] = product[52]; tmp[9] = product[53]; tmp[10] = product[54]; tmp[11] = product[55]; + tmp[12] = tmp[13] = tmp[14] = tmp[15] = 0; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[32]; tmp[25] = product[33]; tmp[26] = product[34]; tmp[27] = product[35]; + tmp[28] = product[40]; tmp[29] = product[41]; tmp[30] = product[42]; tmp[31] = product[43]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[48]; tmp[1] = product[49]; tmp[2] = product[50]; tmp[3] = product[51]; + tmp[4] = product[52]; tmp[5] = product[53]; tmp[6] = product[54]; tmp[7] = product[55]; + tmp[8] = product[56]; tmp[9] = product[57]; tmp[10] = product[58]; tmp[11] = product[59]; + tmp[12] = product[60]; tmp[13] = product[61]; tmp[14] = product[62]; tmp[15] = product[63]; + tmp[16] = tmp[17] = tmp[18] = tmp[19] = 0; + tmp[20] = tmp[21] = tmp[22] = tmp[23] = 0; + tmp[24] = product[36]; tmp[25] = product[37]; tmp[26] = product[38]; tmp[27] = product[39]; + tmp[28] = product[44]; tmp[29] = product[45]; tmp[30] = product[46]; tmp[31] = product[47]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = product[52]; tmp[1] = product[53]; tmp[2] = product[54]; tmp[3] = product[55]; + tmp[4] = product[56]; tmp[5] = product[57]; tmp[6] = product[58]; tmp[7] = product[59]; + tmp[8] = product[60]; tmp[9] = product[61]; tmp[10] = product[62]; tmp[11] = product[63]; + tmp[12] = product[32]; tmp[13] = product[33]; tmp[14] = product[34]; tmp[15] = product[35]; + tmp[16] = product[36]; tmp[17] = product[37]; tmp[18] = product[38]; tmp[19] = product[39]; + tmp[20] = product[40]; tmp[21] = product[41]; tmp[22] = product[42]; tmp[23] = product[43]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + tmp[28] = product[48]; tmp[29] = product[49]; tmp[30] = product[50]; tmp[31] = product[51]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[56]; tmp[1] = product[57]; tmp[2] = product[58]; tmp[3] = product[59]; + tmp[4] = product[60]; tmp[5] = product[61]; tmp[6] = product[62]; tmp[7] = product[63]; + tmp[8] = tmp[9] = tmp[10] = tmp[11] = 0; + tmp[12] = product[36]; tmp[13] = product[37]; tmp[14] = product[38]; tmp[15] = product[39]; + tmp[16] = product[40]; tmp[17] = product[41]; tmp[18] = product[42]; tmp[19] = product[43]; + tmp[20] = product[44]; tmp[21] = product[45]; tmp[22] = product[46]; tmp[23] = product[47]; + tmp[24] = tmp[25] = tmp[26] = tmp[27] = 0; + tmp[28] = product[52]; tmp[29] = product[53]; tmp[30] = product[54]; tmp[31] = product[55]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#elif uECC_WORD_SIZE == 4 +static void vli_mmod_fast_secp256r1(uint32_t *result, uint32_t *product) { + uint32_t tmp[num_words_secp256r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = tmp[1] = tmp[2] = 0; + tmp[3] = product[11]; + tmp[4] = product[12]; + tmp[5] = product[13]; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry = uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[3] = product[12]; + tmp[4] = product[13]; + tmp[5] = product[14]; + tmp[6] = product[15]; + tmp[7] = 0; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[8]; + tmp[1] = product[9]; + tmp[2] = product[10]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[14]; + tmp[7] = product[15]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = product[9]; + tmp[1] = product[10]; + tmp[2] = product[11]; + tmp[3] = product[13]; + tmp[4] = product[14]; + tmp[5] = product[15]; + tmp[6] = product[13]; + tmp[7] = product[8]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = product[11]; + tmp[1] = product[12]; + tmp[2] = product[13]; + tmp[3] = tmp[4] = tmp[5] = 0; + tmp[6] = product[8]; + tmp[7] = product[10]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[12]; + tmp[1] = product[13]; + tmp[2] = product[14]; + tmp[3] = product[15]; + tmp[4] = tmp[5] = 0; + tmp[6] = product[9]; + tmp[7] = product[11]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = product[13]; + tmp[1] = product[14]; + tmp[2] = product[15]; + tmp[3] = product[8]; + tmp[4] = product[9]; + tmp[5] = product[10]; + tmp[6] = 0; + tmp[7] = product[12]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[14]; + tmp[1] = product[15]; + tmp[2] = 0; + tmp[3] = product[9]; + tmp[4] = product[10]; + tmp[5] = product[11]; + tmp[6] = 0; + tmp[7] = product[13]; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#else +static void vli_mmod_fast_secp256r1(uint64_t *result, uint64_t *product) { + uint64_t tmp[num_words_secp256r1]; + int carry; + + /* t */ + uECC_vli_set(result, product, num_words_secp256r1); + + /* s1 */ + tmp[0] = 0; + tmp[1] = product[5] & 0xffffffff00000000ull; + tmp[2] = product[6]; + tmp[3] = product[7]; + carry = (int)uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s2 */ + tmp[1] = product[6] << 32; + tmp[2] = (product[6] >> 32) | (product[7] << 32); + tmp[3] = product[7] >> 32; + carry += uECC_vli_add(tmp, tmp, tmp, num_words_secp256r1); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s3 */ + tmp[0] = product[4]; + tmp[1] = product[5] & 0xffffffff; + tmp[2] = 0; + tmp[3] = product[7]; + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* s4 */ + tmp[0] = (product[4] >> 32) | (product[5] << 32); + tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull); + tmp[2] = product[7]; + tmp[3] = (product[6] >> 32) | (product[4] << 32); + carry += uECC_vli_add(result, result, tmp, num_words_secp256r1); + + /* d1 */ + tmp[0] = (product[5] >> 32) | (product[6] << 32); + tmp[1] = (product[6] >> 32); + tmp[2] = 0; + tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d2 */ + tmp[0] = product[6]; + tmp[1] = product[7]; + tmp[2] = 0; + tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d3 */ + tmp[0] = (product[6] >> 32) | (product[7] << 32); + tmp[1] = (product[7] >> 32) | (product[4] << 32); + tmp[2] = (product[4] >> 32) | (product[5] << 32); + tmp[3] = (product[6] << 32); + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + /* d4 */ + tmp[0] = product[7]; + tmp[1] = product[4] & 0xffffffff00000000ull; + tmp[2] = product[5]; + tmp[3] = product[6] & 0xffffffff00000000ull; + carry -= uECC_vli_sub(result, result, tmp, num_words_secp256r1); + + if (carry < 0) { + do { + carry += uECC_vli_add(result, result, curve_secp256r1.p, num_words_secp256r1); + } while (carry < 0); + } else { + while (carry || uECC_vli_cmp_unsafe(curve_secp256r1.p, result, num_words_secp256r1) != 1) { + carry -= uECC_vli_sub(result, result, curve_secp256r1.p, num_words_secp256r1); + } + } +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256r1) */ + +#endif /* uECC_SUPPORTS_secp256r1 */ + +#if uECC_SUPPORTS_secp256k1 + +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve); +static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); +#if (uECC_OPTIMIZATION_LEVEL > 0) +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product); +#endif + +static const struct uECC_Curve_t curve_secp256k1 = { + num_words_secp256k1, + num_bytes_secp256k1, + 256, /* num_n_bits */ + { BYTES_TO_WORDS_8(2F, FC, FF, FF, FE, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(41, 41, 36, D0, 8C, 5E, D2, BF), + BYTES_TO_WORDS_8(3B, A0, 48, AF, E6, DC, AE, BA), + BYTES_TO_WORDS_8(FE, FF, FF, FF, FF, FF, FF, FF), + BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF) }, + { BYTES_TO_WORDS_8(98, 17, F8, 16, 5B, 81, F2, 59), + BYTES_TO_WORDS_8(D9, 28, CE, 2D, DB, FC, 9B, 02), + BYTES_TO_WORDS_8(07, 0B, 87, CE, 95, 62, A0, 55), + BYTES_TO_WORDS_8(AC, BB, DC, F9, 7E, 66, BE, 79), + + BYTES_TO_WORDS_8(B8, D4, 10, FB, 8F, D0, 47, 9C), + BYTES_TO_WORDS_8(19, 54, 85, A6, 48, B4, 17, FD), + BYTES_TO_WORDS_8(A8, 08, 11, 0E, FC, FB, A4, 5D), + BYTES_TO_WORDS_8(65, C4, A3, 26, 77, DA, 3A, 48) }, + { BYTES_TO_WORDS_8(07, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00), + BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00) }, + &double_jacobian_secp256k1, +#if uECC_SUPPORT_COMPRESSED_POINT + &mod_sqrt_default, +#endif + &x_side_secp256k1, +#if (uECC_OPTIMIZATION_LEVEL > 0) + &vli_mmod_fast_secp256k1 +#endif +}; + +uECC_Curve uECC_secp256k1(void) { return &curve_secp256k1; } + + +/* Double in place */ +static void double_jacobian_secp256k1(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve) { + /* t1 = X, t2 = Y, t3 = Z */ + uECC_word_t t4[num_words_secp256k1]; + uECC_word_t t5[num_words_secp256k1]; + + if (uECC_vli_isZero(Z1, num_words_secp256k1)) { + return; + } + + uECC_vli_modSquare_fast(t5, Y1, curve); /* t5 = y1^2 */ + uECC_vli_modMult_fast(t4, X1, t5, curve); /* t4 = x1*y1^2 = A */ + uECC_vli_modSquare_fast(X1, X1, curve); /* t1 = x1^2 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = y1^4 */ + uECC_vli_modMult_fast(Z1, Y1, Z1, curve); /* t3 = y1*z1 = z3 */ + + uECC_vli_modAdd(Y1, X1, X1, curve->p, num_words_secp256k1); /* t2 = 2*x1^2 */ + uECC_vli_modAdd(Y1, Y1, X1, curve->p, num_words_secp256k1); /* t2 = 3*x1^2 */ + if (uECC_vli_testBit(Y1, 0)) { + uECC_word_t carry = uECC_vli_add(Y1, Y1, curve->p, num_words_secp256k1); + uECC_vli_rshift1(Y1, num_words_secp256k1); + Y1[num_words_secp256k1 - 1] |= carry << (uECC_WORD_BITS - 1); + } else { + uECC_vli_rshift1(Y1, num_words_secp256k1); + } + /* t2 = 3/2*(x1^2) = B */ + + uECC_vli_modSquare_fast(X1, Y1, curve); /* t1 = B^2 */ + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - A */ + uECC_vli_modSub(X1, X1, t4, curve->p, num_words_secp256k1); /* t1 = B^2 - 2A = x3 */ + + uECC_vli_modSub(t4, t4, X1, curve->p, num_words_secp256k1); /* t4 = A - x3 */ + uECC_vli_modMult_fast(Y1, Y1, t4, curve); /* t2 = B * (A - x3) */ + uECC_vli_modSub(Y1, Y1, t5, curve->p, num_words_secp256k1); /* t2 = B * (A - x3) - y1^4 = y3 */ +} + +/* Computes result = x^3 + b. result must not overlap x. */ +static void x_side_secp256k1(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve) { + uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */ + uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 */ + uECC_vli_modAdd(result, result, curve->b, curve->p, num_words_secp256k1); /* r = x^3 + b */ +} + +#if (uECC_OPTIMIZATION_LEVEL > 0 && !asm_mmod_fast_secp256k1) +static void omega_mult_secp256k1(uECC_word_t *result, const uECC_word_t *right); +static void vli_mmod_fast_secp256k1(uECC_word_t *result, uECC_word_t *product) { + uECC_word_t tmp[2 * num_words_secp256k1]; + uECC_word_t carry; + + uECC_vli_clear(tmp, num_words_secp256k1); + uECC_vli_clear(tmp + num_words_secp256k1, num_words_secp256k1); + + omega_mult_secp256k1(tmp, product + num_words_secp256k1); /* (Rq, q) = q * c */ + + carry = uECC_vli_add(result, product, tmp, num_words_secp256k1); /* (C, r) = r + q */ + uECC_vli_clear(product, num_words_secp256k1); + omega_mult_secp256k1(product, tmp + num_words_secp256k1); /* Rq*c */ + carry += uECC_vli_add(result, result, product, num_words_secp256k1); /* (C1, r) = r + Rq*c */ + + while (carry > 0) { + --carry; + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + } + if (uECC_vli_cmp_unsafe(result, curve_secp256k1.p, num_words_secp256k1) > 0) { + uECC_vli_sub(result, result, curve_secp256k1.p, num_words_secp256k1); + } +} + +#if uECC_WORD_SIZE == 1 +static void omega_mult_secp256k1(uint8_t * result, const uint8_t * right) { + /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t k; + + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + muladd(0xD1, right[0], &r0, &r1, &r2); + result[0] = r0; + r0 = r1; + r1 = r2; + /* r2 is still 0 */ + + for (k = 1; k < num_words_secp256k1; ++k) { + muladd(0x03, right[k - 1], &r0, &r1, &r2); + muladd(0xD1, right[k], &r0, &r1, &r2); + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + muladd(0x03, right[num_words_secp256k1 - 1], &r0, &r1, &r2); + result[num_words_secp256k1] = r0; + result[num_words_secp256k1 + 1] = r1; + /* add the 2^32 multiple */ + result[4 + num_words_secp256k1] = + uECC_vli_add(result + 4, result + 4, right, num_words_secp256k1); +} +#elif uECC_WORD_SIZE == 4 +static void omega_mult_secp256k1(uint32_t * result, const uint32_t * right) { + /* Multiply by (2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + uint32_t carry = 0; + wordcount_t k; + + for (k = 0; k < num_words_secp256k1; ++k) { + uint64_t p = (uint64_t)0x3D1 * right[k] + carry; + result[k] = (uint32_t) p; + carry = p >> 32; + } + result[num_words_secp256k1] = carry; + /* add the 2^32 multiple */ + result[1 + num_words_secp256k1] = + uECC_vli_add(result + 1, result + 1, right, num_words_secp256k1); +} +#else +static void omega_mult_secp256k1(uint64_t * result, const uint64_t * right) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t k; + + /* Multiply by (2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1). */ + for (k = 0; k < num_words_secp256k1; ++k) { + muladd(0x1000003D1ull, right[k], &r0, &r1, &r2); + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words_secp256k1] = r0; +} +#endif /* uECC_WORD_SIZE */ +#endif /* (uECC_OPTIMIZATION_LEVEL > 0 && && !asm_mmod_fast_secp256k1) */ + +#endif /* uECC_SUPPORTS_secp256k1 */ + +#endif /* _UECC_CURVE_SPECIFIC_H_ */ diff --git a/core/embed/ble_firmware/uecc/emk_project.py b/core/embed/ble_firmware/uecc/emk_project.py new file mode 100644 index 000000000..957dd7920 --- /dev/null +++ b/core/embed/ble_firmware/uecc/emk_project.py @@ -0,0 +1,132 @@ +import os + +c, link, asm, utils = emk.module("c", "link", "asm", "utils") + +default_compile_flags = ["-fvisibility=hidden", "-Wall", "-Wextra", "-Wshadow", "-Werror", "-Wno-missing-field-initializers", "-Wno-unused-parameter", \ + "-Wno-comment", "-Wno-unused", "-Wno-unknown-pragmas"] +default_link_flags = [] +opt_flags = {"dbg":["-g"], "std":["-O2"], "max":["-O3"], "small":["-Os"]} +opt_link_flags = {"dbg":[], "std":[], "max":[], "small":[]} +c_flags = ["-std=c99"] +cxx_flags = ["-std=c++11", "-Wno-reorder", "-fno-rtti", "-fno-exceptions"] +c_link_flags = [] +cxx_link_flags = ["-fno-rtti", "-fno-exceptions"] + +if "root" in emk.options: + root = emk.options["root"] +else: + root = "/" + +def setup_build_dir(): + build_arch = None + if "arch" in emk.options: + build_arch = emk.options["arch"] + elif not emk.cleaning: + build_arch = "osx" + emk.options["arch"] = build_arch + + opt_level = None + if "opt" in emk.options: + level = emk.options["opt"] + if level in opt_flags: + opt_level = level + else: + emk.log.warning("Unknown optimization level '%s'" % (level)) + elif not emk.cleaning: + opt_level = "dbg" + emk.options["opt"] = opt_level + + dirs = ["__build__"] + if build_arch: + dirs.append(build_arch) + if opt_level: + dirs.append(opt_level) + emk.build_dir = os.path.join(*dirs) + +def setup_osx(): + global c + global link + + flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"] + c.flags.extend(flags) + c.cxx.flags += ["-stdlib=libc++"] + link.cxx.flags += ["-stdlib=libc++"] + + link_flags = [("-arch", "x86_64")] + link.local_flags.extend(link_flags) + +def setup_avr(): + global c + global link + + c.compiler = c.GccCompiler(root + "Projects/avr-tools/bin/avr-") + c.flags += ["-mmcu=atmega256rfr2", "-ffunction-sections", "-fdata-sections"] + link.linker = link.GccLinker(root + "Projects/avr-tools/bin/avr-") + link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"] + link.strip = True + +def setup_arm_thumb(): + global c + global link + global asm + global utils + + asm.assembler = asm.GccAssembler(root + "cross/arm_cortex/bin/arm-none-eabi-") + c.compiler = c.GccCompiler(root + "cross/arm_cortex/bin/arm-none-eabi-") + link.linker = link.GccLinker(root + "cross/arm_cortex/bin/arm-none-eabi-") + + c.flags.extend(["-mcpu=cortex-m0", "-mthumb", "-ffunction-sections", "-fdata-sections", "-fno-builtin-fprintf", "-fno-builtin-printf"]) + c.defines["LPC11XX"] = 1 + + link.local_flags.extend(["-mcpu=cortex-m0", "-mthumb", "-nostartfiles", "-nostdlib", "-Wl,--gc-sections"]) + link.local_flags.extend(["-Tflash.lds", "-L" + root + "Projects/lpc11xx/core", root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o"]) + link.local_syslibs += ["gcc"] + link.depdirs += [root + "Projects/lpc11xx/stdlib"] + + def do_objcopy(produces, requires): + utils.call(root + "cross/arm_cortex/bin/arm-none-eabi-objcopy", "-O", "binary", requires[0], produces[0]) + + def handle_exe(path): + emk.depend(path, root + "Projects/lpc11xx/core/" + emk.build_dir + "/board_cstartup.o") + emk.rule(do_objcopy, path + ".bin", path, cwd_safe=True, ex_safe=True) + emk.autobuild(path + ".bin") + + link.exe_funcs.append(handle_exe) + link.strip = True + + emk.recurse(root + "Projects/lpc11xx/core") + +def setup_linux_rpi(): + global c + global link + + c.compiler = c.GccCompiler("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") + link.linker = link.GccLinker("/Volumes/xtools/arm-none-linux-gnueabi/bin/arm-none-linux-gnueabi-") + + c.flags.extend(["-fomit-frame-pointer"]) + +setup_build_dir() + +setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb, "rpi": setup_linux_rpi} + +if not emk.cleaning: + build_arch = emk.options["arch"] + opt_level = emk.options["opt"] + + c.flags.extend(default_compile_flags) + c.flags.extend(opt_flags[opt_level]) + c.c.flags.extend(c_flags) + c.cxx.flags.extend(cxx_flags) + link.local_flags.extend(default_link_flags) + link.local_flags.extend(opt_link_flags[opt_level]) + link.c.local_flags.extend(c_link_flags) + link.cxx.local_flags.extend(cxx_link_flags) + + c.include_dirs.append("$:proj:$") + + if build_arch in setup_funcs: + setup_funcs[build_arch]() + else: + raise emk.BuildError("Unknown target arch '%s'" % (build_arch)) + + c.defines["TARGET_ARCH_" + build_arch.upper()] = 1 diff --git a/core/embed/ble_firmware/uecc/emk_rules.py b/core/embed/ble_firmware/uecc/emk_rules.py new file mode 100644 index 000000000..b1d76c81a --- /dev/null +++ b/core/embed/ble_firmware/uecc/emk_rules.py @@ -0,0 +1,3 @@ +c, link = emk.module("c", "link") + +emk.subdir("test") diff --git a/core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino b/core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino new file mode 100644 index 000000000..64a0be50f --- /dev/null +++ b/core/embed/ble_firmware/uecc/examples/ecc_test/ecc_test.ino @@ -0,0 +1,80 @@ +#include + +static int RNG(uint8_t *dest, unsigned size) { + // Use the least-significant bits from the ADC for an unconnected pin (or connected to a source of + // random noise). This can take a long time to generate random data if the result of analogRead(0) + // doesn't change very frequently. + while (size) { + uint8_t val = 0; + for (unsigned i = 0; i < 8; ++i) { + int init = analogRead(0); + int count = 0; + while (analogRead(0) == init) { + ++count; + } + + if (count == 0) { + val = (val << 1) | (init & 0x01); + } else { + val = (val << 1) | (count & 0x01); + } + } + *dest = val; + ++dest; + --size; + } + // NOTE: it would be a good idea to hash the resulting random data using SHA-256 or similar. + return 1; +} + +void setup() { + Serial.begin(115200); + Serial.print("Testing ecc\n"); + uECC_set_rng(&RNG); +} + +void loop() { + const struct uECC_Curve_t * curve = uECC_secp160r1(); + uint8_t private1[21]; + uint8_t private2[21]; + + uint8_t public1[40]; + uint8_t public2[40]; + + uint8_t secret1[20]; + uint8_t secret2[20]; + + unsigned long a = millis(); + uECC_make_key(public1, private1, curve); + unsigned long b = millis(); + + Serial.print("Made key 1 in "); Serial.println(b-a); + a = millis(); + uECC_make_key(public2, private2, curve); + b = millis(); + Serial.print("Made key 2 in "); Serial.println(b-a); + + a = millis(); + int r = uECC_shared_secret(public2, private1, secret1, curve); + b = millis(); + Serial.print("Shared secret 1 in "); Serial.println(b-a); + if (!r) { + Serial.print("shared_secret() failed (1)\n"); + return; + } + + a = millis(); + r = uECC_shared_secret(public1, private2, secret2, curve); + b = millis(); + Serial.print("Shared secret 2 in "); Serial.println(b-a); + if (!r) { + Serial.print("shared_secret() failed (2)\n"); + return; + } + + if (memcmp(secret1, secret2, 20) != 0) { + Serial.print("Shared secrets are not identical!\n"); + } else { + Serial.print("Shared secrets are identical\n"); + } +} diff --git a/core/embed/ble_firmware/uecc/library.properties b/core/embed/ble_firmware/uecc/library.properties new file mode 100644 index 000000000..390bdc87a --- /dev/null +++ b/core/embed/ble_firmware/uecc/library.properties @@ -0,0 +1,9 @@ +name=micro-ecc +version=1.0.0 +author=Kenneth MacKay +maintainer=Kenneth MacKay +sentence=uECC +paragraph=A small and fast ECDH and ECDSA implementation for 8-bit, 32-bit, and 64-bit processors. +category=Other +url=https://github.com/kmackay/micro-ecc +architectures=* diff --git a/core/embed/ble_firmware/uecc/platform-specific.inc b/core/embed/ble_firmware/uecc/platform-specific.inc new file mode 100644 index 000000000..7e0373f50 --- /dev/null +++ b/core/embed/ble_firmware/uecc/platform-specific.inc @@ -0,0 +1,94 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_PLATFORM_SPECIFIC_H_ +#define _UECC_PLATFORM_SPECIFIC_H_ + +#include "types.h" + +#if (defined(_WIN32) || defined(_WIN64)) +/* Windows */ + +// use pragma syntax to prevent tweaking the linker script for getting CryptXYZ function +#pragma comment(lib, "crypt32.lib") +#pragma comment(lib, "advapi32.lib") + +#define WIN32_LEAN_AND_MEAN +#include +#include + +static int default_RNG(uint8_t *dest, unsigned size) { + HCRYPTPROV prov; + if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + return 0; + } + + CryptGenRandom(prov, size, (BYTE *)dest); + CryptReleaseContext(prov, 0); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(unix) || defined(__linux__) || defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__)) || defined(uECC_POSIX) + +/* Some POSIX-like system with /dev/urandom or /dev/random. */ +#include +#include +#include + +#ifndef O_CLOEXEC + #define O_CLOEXEC 0 +#endif + +static int default_RNG(uint8_t *dest, unsigned size) { + int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + fd = open("/dev/random", O_RDONLY | O_CLOEXEC); + if (fd == -1) { + return 0; + } + } + + char *ptr = (char *)dest; + size_t left = size; + while (left > 0) { + ssize_t bytes_read = read(fd, ptr, left); + if (bytes_read <= 0) { // read failed + close(fd); + return 0; + } + left -= bytes_read; + ptr += bytes_read; + } + + close(fd); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(RIOT_VERSION) + +#include + +static int default_RNG(uint8_t *dest, unsigned size) { + random_bytes(dest, size); + return 1; +} +#define default_RNG_defined 1 + +#elif defined(NRF52_SERIES) + +#include "app_error.h" +#include "nrf_crypto_rng.h" + +static int default_RNG(uint8_t *dest, unsigned size) +{ + // make sure to call nrf_crypto_init and nrf_crypto_rng_init first + ret_code_t ret_code = nrf_crypto_rng_vector_generate(dest, size); + return (ret_code == NRF_SUCCESS) ? 1 : 0; +} +#define default_RNG_defined 1 + +#endif /* platform */ + +#endif /* _UECC_PLATFORM_SPECIFIC_H_ */ diff --git a/core/embed/ble_firmware/uecc/scripts/mult_arm.py b/core/embed/ble_firmware/uecc/scripts/mult_arm.py new file mode 100755 index 000000000..402ace190 --- /dev/null +++ b/core/embed/ble_firmware/uecc/scripts/mult_arm.py @@ -0,0 +1,188 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in 32-bit words" + sys.exit(1) + +size = int(sys.argv[1]) + +full_rows = size // 3 +init_size = size % 3 + +if init_size == 0: + full_rows = full_rows - 1 + init_size = 3 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +rx = [3, 4, 5] +ry = [6, 7, 8] + +#### set up registers +emit("add r0, %s", (size - init_size) * 4) # move z +emit("add r2, %s", (size - init_size) * 4) # move y + +emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size)])) +emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(init_size)])) + +print "" +if init_size == 1: + emit("umull r9, r10, r3, r6") + emit("stmia r0!, {r9, r10}") +else: + #### first two multiplications of initial block + emit("umull r11, r12, r3, r6") + emit("stmia r0!, {r11}") + print "" + emit("mov r10, #0") + emit("umull r11, r9, r3, r7") + emit("adds r12, r12, r11") + emit("adc r9, r9, #0") + emit("umull r11, r14, r4, r6") + emit("adds r12, r12, r11") + emit("adcs r9, r9, r14") + emit("adc r10, r10, #0") + emit("stmia r0!, {r12}") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [9, 10, 11, 12, 14] + if init_size == 3: + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 2): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i + 1], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[init_size-1], ry[init_size-1]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("stmia r0!, {r%s}", acc[0]) + emit("stmia r0!, {r%s}", acc[1]) +print "" + +#### reset y and z pointers +emit("sub r0, %s", (2 * init_size + 3) * 4) +emit("sub r2, %s", (init_size + 3) * 4) + +#### load y registers +emit("ldmia r2!, {%s}", ", ".join(["r%s" % (ry[i]) for i in xrange(3)])) + +#### load additional x registers +if init_size != 3: + emit("ldmia r1!, {%s}", ", ".join(["r%s" % (rx[i]) for i in xrange(init_size, 3)])) +print "" + +prev_size = init_size +for row in xrange(full_rows): + emit("umull r11, r12, r3, r6") + emit("stmia r0!, {r11}") + print "" + emit("mov r10, #0") + emit("umull r11, r9, r3, r7") + emit("adds r12, r12, r11") + emit("adc r9, r9, #0") + emit("umull r11, r14, r4, r6") + emit("adds r12, r12, r11") + emit("adcs r9, r9, r14") + emit("adc r10, r10, #0") + emit("stmia r0!, {r12}") + print "" + + acc = [9, 10, 11, 12, 14] + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], rx[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + #### now we need to start shifting x and loading from z + x_regs = [3, 4, 5] + for r in xrange(0, prev_size): + x_regs = x_regs[1:] + x_regs[:1] + emit("ldmia r1!, {r%s}", x_regs[2]) + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], ry[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # done shifting x, start shifting y + y_regs = [6, 7, 8] + for r in xrange(0, prev_size): + y_regs = y_regs[1:] + y_regs[:1] + emit("ldmia r2!, {r%s}", y_regs[2]) + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 3): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i], y_regs[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("ldr r%s, [r0]", acc[3]) # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # done both shifts, do remaining corner + emit("mov r%s, #0", acc[2]) + for i in xrange(0, 2): + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[i + 1], y_regs[2 - i]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + emit("stmia r0!, {r%s}", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + emit("umull r%s, r%s, r%s, r%s", acc[3], acc[4], x_regs[2], y_regs[2]) + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[3]) + emit("adc r%s, r%s, r%s", acc[1], acc[1], acc[4]) + emit("stmia r0!, {r%s}", acc[0]) + emit("stmia r0!, {r%s}", acc[1]) + print "" + + prev_size = prev_size + 3 + if row < full_rows - 1: + #### reset x, y and z pointers + emit("sub r0, %s", (2 * prev_size + 3) * 4) + emit("sub r1, %s", prev_size * 4) + emit("sub r2, %s", (prev_size + 3) * 4) + + #### load x and y registers + emit("ldmia r1!, {%s}", ",".join(["r%s" % (rx[i]) for i in xrange(3)])) + emit("ldmia r2!, {%s}", ",".join(["r%s" % (ry[i]) for i in xrange(3)])) + + print "" diff --git a/core/embed/ble_firmware/uecc/scripts/mult_avr.py b/core/embed/ble_firmware/uecc/scripts/mult_avr.py new file mode 100755 index 000000000..d40e4c23d --- /dev/null +++ b/core/embed/ble_firmware/uecc/scripts/mult_avr.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +full_rows = size // 10 +init_size = size % 10 + +if init_size == 0: + full_rows = full_rows - 1 + init_size = 10 + +def rx(i): + return i + 2 + +def ry(i): + return i + 12 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +#### set up registers +emit("adiw r30, %s", size - init_size) # move z +emit("adiw r28, %s", size - init_size) # move y + +for i in xrange(init_size): + emit("ld r%s, x+", rx(i)) +for i in xrange(init_size): + emit("ld r%s, y+", ry(i)) + +emit("ldi r25, 0") +print "" +if init_size == 1: + emit("mul r2, r12") + emit("st z+, r0") + emit("st z+, r1") +else: + #### first two multiplications of initial block + emit("ldi r23, 0") + emit("mul r2, r12") + emit("st z+, r0") + emit("mov r22, r1") + print "" + emit("ldi r24, 0") + emit("mul r2, r13") + emit("add r22, r0") + emit("adc r23, r1") + emit("mul r3, r12") + emit("add r22, r0") + emit("adc r23, r1") + emit("adc r24, r25") + emit("st z+, r22") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [23, 24, 22] + for r in xrange(2, init_size): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, r+1): + emit("mul r%s, r%s", rx(i), ry(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + for r in xrange(1, init_size-1): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, init_size-r): + emit("mul r%s, r%s", rx(r+i), ry((init_size-1) - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + emit("mul r%s, r%s", rx(init_size-1), ry(init_size-1)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) +print "" + +#### reset y and z pointers +emit("sbiw r30, %s", 2 * init_size + 10) +emit("sbiw r28, %s", init_size + 10) + +#### load y registers +for i in xrange(10): + emit("ld r%s, y+", ry(i)) + +#### load additional x registers +for i in xrange(init_size, 10): + emit("ld r%s, x+", rx(i)) +print "" + +prev_size = init_size +for row in xrange(full_rows): + #### do x = 0-9, y = 0-9 multiplications + emit("ldi r23, 0") + emit("mul r2, r12") + emit("st z+, r0") + emit("mov r22, r1") + print "" + emit("ldi r24, 0") + emit("mul r2, r13") + emit("add r22, r0") + emit("adc r23, r1") + emit("mul r3, r12") + emit("add r22, r0") + emit("adc r23, r1") + emit("adc r24, r25") + emit("st z+, r22") + print "" + + acc = [23, 24, 22] + for r in xrange(2, 10): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, r+1): + emit("mul r%s, r%s", rx(i), ry(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + #### now we need to start shifting x and loading from z + x_regs = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11] + for r in xrange(0, prev_size): + x_regs = x_regs[1:] + x_regs[:1] + emit("ld r%s, x+", x_regs[9]) # load next byte of left + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10): + emit("mul r%s, r%s", x_regs[i], ry(9 - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) # store next byte (z increments) + print "" + acc = acc[1:] + acc[:1] + + # done shifting x, start shifting y + y_regs = [12, 13, 14, 15, 16, 17, 18, 19, 20, 21] + for r in xrange(0, prev_size): + y_regs = y_regs[1:] + y_regs[:1] + emit("ld r%s, y+", y_regs[9]) # load next byte of right + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10): + emit("mul r%s, r%s", x_regs[i], y_regs[9 -i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) # store next byte (z increments) + print "" + acc = acc[1:] + acc[:1] + + # done both shifts, do remaining corner + for r in xrange(1, 9): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, 10-r): + emit("mul r%s, r%s", x_regs[r+i], y_regs[9 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, r25", acc[2]) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + emit("mul r%s, r%s", x_regs[9], y_regs[9]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) + print "" + + prev_size = prev_size + 10 + if row < full_rows - 1: + #### reset x, y and z pointers + emit("sbiw r30, %s", 2 * prev_size + 10) + emit("sbiw r28, %s", prev_size + 10) + emit("sbiw r26, %s", prev_size) + + #### load x and y registers + for i in xrange(10): + emit("ld r%s, x+", rx(i)) + emit("ld r%s, y+", ry(i)) + print "" + +emit("eor r1, r1") diff --git a/core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py b/core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py new file mode 100755 index 000000000..f6e654f6a --- /dev/null +++ b/core/embed/ble_firmware/uecc/scripts/mult_avr_extra.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +def lhi(i): + return i + 2 + +def rhi(i): + return i + 6 + +left_lo = [10, 11, 12, 13] +right_lo = [14, 15, 16, 17] + +def llo(i): + return left_lo[i] + +def rlo(i): + return right_lo[i] + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +def update_low(): + global left_lo + global right_lo + left_lo = left_lo[1:] + left_lo[:1] + right_lo = right_lo[1:] + right_lo[:1] + emit("ld r%s, x+", left_lo[3]) + emit("ld r%s, y+", right_lo[3]) + +accum = [19, 20, 21] + +def acc(i): + return accum[i] + +def rotate_acc(): + global accum + accum = accum[1:] + accum[:1] + +# Load high values +for i in xrange(4): + emit("ld r%s, x+", lhi(i)) + emit("ld r%s, y+", rhi(i)) + +emit("sbiw r26, %s", size + 4) +emit("sbiw r28, %s", size + 4) +emit("sbiw r30, %s", size) + +# Load low values +for i in xrange(4): + emit("ld r%s, x+", llo(i)) + emit("ld r%s, y+", rlo(i)) +print "" + +# Compute initial triangles +emit("mul r%s, r%s", lhi(0), rlo(0)) +emit("mov r%s, r0", acc(0)) +emit("mov r%s, r1", acc(1)) +emit("ldi r%s, 0", acc(2)) +emit("ld r0, z") +emit("add r%s, r0", acc(0)) +emit("adc r%s, r25", acc(1)) +emit("mul r%s, r%s", rhi(0), llo(0)) +emit("add r%s, r0", acc(0)) +emit("adc r%s, r1", acc(1)) +emit("adc r%s, r25", acc(2)) +emit("st z+, r%s", acc(0)) +print "" +rotate_acc() + +for i in xrange(1, 4): + emit("ldi r%s, 0", acc(2)) + emit("ld r0, z") + emit("add r%s, r0", acc(0)) + emit("adc r%s, r25", acc(1)) + for j in xrange(i + 1): + emit("mul r%s, r%s", lhi(j), rlo(i-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("mul r%s, r%s", rhi(j), llo(i-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +# Compute rows overlapping old block +for i in xrange(4, size): + emit("ldi r%s, 0", acc(2)) + emit("ld r0, z") + emit("add r%s, r0", acc(0)) + emit("adc r%s, r25", acc(1)) + update_low() + for j in xrange(4): + emit("mul r%s, r%s", lhi(j), rlo(3-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("mul r%s, r%s", rhi(j), llo(3-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +# Compute new triangle +left_combined = [llo(1), llo(2), llo(3), lhi(0), lhi(1), lhi(2), lhi(3)] +right_combined = [rlo(1), rlo(2), rlo(3), rhi(0), rhi(1), rhi(2), rhi(3)] + +def left(i): + return left_combined[i] + +def right(i): + return right_combined[i] + +for i in xrange(6): + emit("ldi r%s, 0", acc(2)) + for j in xrange(7 - i): + emit("mul r%s, r%s", left(i+j), right(6-j)) + emit("add r%s, r0", acc(0)) + emit("adc r%s, r1", acc(1)) + emit("adc r%s, r25", acc(2)) + emit("st z+, r%s", acc(0)) + print "" + rotate_acc() + +emit("mul r%s, r%s", left(6), right(6)) +emit("add r%s, r0", acc(0)) +emit("adc r%s, r1", acc(1)) +emit("st z+, r%s", acc(0)) +emit("st z+, r%s", acc(1)) +emit("adiw r26, 4") +emit("adiw r28, 4") diff --git a/core/embed/ble_firmware/uecc/scripts/square_arm.py b/core/embed/ble_firmware/uecc/scripts/square_arm.py new file mode 100755 index 000000000..5330c7e63 --- /dev/null +++ b/core/embed/ble_firmware/uecc/scripts/square_arm.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in 32-bit words" + sys.exit(1) + +size = int(sys.argv[1]) + +if size > 8: + print "This script doesn't work with integer size %s due to laziness" % (size) + sys.exit(1) + +init_size = 0 +if size > 6: + init_size = size - 6 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +def mulacc(acc, r1, r2): + if size <= 6: + emit("umull r1, r14, r%s, r%s", r1, r2) + emit("adds r%s, r%s, r1", acc[0], acc[0]) + emit("adcs r%s, r%s, r14", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + else: + emit("mov r14, r%s", acc[1]) + emit("umlal r%s, r%s, r%s, r%s", acc[0], acc[1], r1, r2) + emit("cmp r14, r%s", acc[1]) + emit("it hi") + emit("adchi r%s, r%s, #0", acc[2], acc[2]) + +r = [2, 3, 4, 5, 6, 7] + +s = size - init_size + +if init_size == 1: + emit("ldmia r1!, {r2}") + emit("add r1, %s", (size - init_size * 2) * 4) + emit("ldmia r1!, {r5}") + + emit("add r0, %s", (size - init_size) * 4) + emit("umull r8, r9, r2, r5") + emit("stmia r0!, {r8, r9}") + + emit("sub r0, %s", (size + init_size) * 4) + emit("sub r1, %s", (size) * 4) + print "" +elif init_size == 2: + emit("ldmia r1!, {r2, r3}") + emit("add r1, %s", (size - init_size * 2) * 4) + emit("ldmia r1!, {r5, r6}") + + emit("add r0, %s", (size - init_size) * 4) + print "" + + emit("umull r8, r9, r2, r5") + emit("stmia r0!, {r8}") + print "" + + emit("umull r12, r10, r2, r6") + emit("adds r9, r9, r12") + emit("adc r10, r10, #0") + emit("stmia r0!, {r9}") + print "" + + emit("umull r8, r9, r3, r6") + emit("adds r10, r10, r8") + emit("adc r11, r9, #0") + emit("stmia r0!, {r10, r11}") + print "" + + emit("sub r0, %s", (size + init_size) * 4) + emit("sub r1, %s", (size) * 4) + +# load input words +emit("ldmia r1!, {%s}", ", ".join(["r%s" % (r[i]) for i in xrange(s)])) +print "" + +emit("umull r11, r12, r2, r2") +emit("stmia r0!, {r11}") +print "" +emit("mov r9, #0") +emit("umull r10, r11, r2, r3") +emit("adds r12, r12, r10") +emit("adcs r8, r11, #0") +emit("adc r9, r9, #0") +emit("adds r12, r12, r10") +emit("adcs r8, r8, r11") +emit("adc r9, r9, #0") +emit("stmia r0!, {r12}") +print "" +emit("mov r10, #0") +emit("umull r11, r12, r2, r4") +emit("adds r11, r11, r11") +emit("adcs r12, r12, r12") +emit("adc r10, r10, #0") +emit("adds r8, r8, r11") +emit("adcs r9, r9, r12") +emit("adc r10, r10, #0") +emit("umull r11, r12, r3, r3") +emit("adds r8, r8, r11") +emit("adcs r9, r9, r12") +emit("adc r10, r10, #0") +emit("stmia r0!, {r8}") +print "" + +acc = [8, 9, 10] +old_acc = [11, 12] +for i in xrange(3, s): + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], r[0], r[i]) + for j in xrange(1, (i+1)//2): + mulacc(acc, r[j], r[i-j]) + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word (if any) + if ((i+1) % 2) != 0: + mulacc(acc, r[i//2], r[i//2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +regs = list(r) +for i in xrange(init_size): + regs = regs[1:] + regs[:1] + emit("ldmia r1!, {r%s}", regs[5]) + + for limit in [4, 5]: + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[0], regs[limit]) + for j in xrange(1, (limit+1)//2): + mulacc(acc, regs[j], regs[limit-j]) + + emit("ldr r14, [r0]") # load stored value from initial block, and add to accumulator + emit("adds r%s, r%s, r14", acc[0], acc[0]) + emit("adcs r%s, r%s, #0", acc[1], acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word + if limit == 4: + mulacc(acc, regs[2], regs[2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +for i in xrange(1, s-3): + emit("mov r%s, #0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("umull r%s, r%s, r%s, r%s", acc[0], acc[1], regs[i], regs[s - 1]) + for j in xrange(1, (s-i)//2): + mulacc(acc, regs[i+j], regs[s - 1 - j]) + + # multiply by 2 + emit("adds r%s, r%s, r%s", acc[0], acc[0], acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], acc[1]) + emit("adc r%s, r%s, r%s", acc[2], acc[2], acc[2]) + + # add equal word (if any) + if ((s-i) % 2) != 0: + mulacc(acc, regs[i + (s-i)//2], regs[i + (s-i)//2]) + + # add old accumulator + emit("adds r%s, r%s, r%s", acc[0], acc[0], old_acc[0]) + emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) + emit("adc r%s, r%s, #0", acc[2], acc[2]) + + # store + emit("stmia r0!, {r%s}", acc[0]) + print "" + +acc = acc[1:] + acc[:1] +emit("mov r%s, #0", acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 3], regs[s - 1]) +emit("adds r1, r1, r1") +emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("stmia r0!, {r%s}", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("mov r%s, #0", acc[2]) +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 2], regs[s - 1]) +emit("adds r1, r1, r1") +emit("adcs r%s, r%s, r%s", old_acc[1], old_acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("adc r%s, r%s, #0", acc[2], acc[2]) +emit("stmia r0!, {r%s}", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("umull r1, r%s, r%s, r%s", old_acc[1], regs[s - 1], regs[s - 1]) +emit("adds r%s, r%s, r1", acc[0], acc[0]) +emit("adcs r%s, r%s, r%s", acc[1], acc[1], old_acc[1]) +emit("stmia r0!, {r%s}", acc[0]) +emit("stmia r0!, {r%s}", acc[1]) diff --git a/core/embed/ble_firmware/uecc/scripts/square_avr.py b/core/embed/ble_firmware/uecc/scripts/square_avr.py new file mode 100755 index 000000000..6571c3b3c --- /dev/null +++ b/core/embed/ble_firmware/uecc/scripts/square_avr.py @@ -0,0 +1,327 @@ +#!/usr/bin/env python + +import sys + +if len(sys.argv) < 2: + print "Provide the integer size in bytes" + sys.exit(1) + +size = int(sys.argv[1]) + +if size > 40: + print "This script doesn't work with integer size %s due to laziness" % (size) + sys.exit(1) + +init_size = size - 20 +if size < 20: + init_size = 0 + +def rg(i): + return i + 2 + +def lo(i): + return i + 2 + +def hi(i): + return i + 12 + +def emit(line, *args): + s = '"' + line + r' \n\t"' + print s % args + +#### set up registers +zero = "r25" +emit("ldi %s, 0", zero) # zero register + +if init_size > 0: + emit("movw r28, r26") # y = x + h = (init_size + 1)//2 + + for i in xrange(h): + emit("ld r%s, x+", lo(i)) + emit("adiw r28, %s", size - init_size) # move y to other end + for i in xrange(h): + emit("ld r%s, y+", hi(i)) + + emit("adiw r30, %s", size - init_size) # move z + + if init_size == 1: + emit("mul %s, %s", lo(0), hi(0)) + emit("st z+, r0") + emit("st z+, r1") + else: + #### first one + print "" + emit("ldi r23, 0") + emit("mul %s, %s", lo(0), hi(0)) + emit("st z+, r0") + emit("mov r22, r1") + print "" + + #### rest of initial block, with moving accumulator registers + acc = [22, 23, 24] + for r in xrange(1, h): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (r+2)//2): + emit("mul r%s, r%s", lo(i), hi(r - i)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + lo_r = range(2, 2 + h) + hi_r = range(12, 12 + h) + + # now we need to start loading more from the high end + for r in xrange(h, init_size): + hi_r = hi_r[1:] + hi_r[:1] + emit("ld r%s, y+", hi_r[h-1]) + + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (r+2)//2): + emit("mul r%s, r%s", lo(i), hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + # loaded all of the high end bytes; now need to start loading the rest of the low end + for r in xrange(1, init_size-h): + lo_r = lo_r[1:] + lo_r[:1] + emit("ld r%s, x+", lo_r[h-1]) + + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (init_size+1 - r)//2): + emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + + lo_r = lo_r[1:] + lo_r[:1] + emit("ld r%s, x+", lo_r[h-1]) + + # now we have loaded everything, and we just need to finish the last corner + for r in xrange(init_size-h, init_size-1): + emit("ldi r%s, 0", acc[2]) + for i in xrange(0, (init_size+1 - r)//2): + emit("mul r%s, r%s", lo_r[i], hi_r[h - 1 - i]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + emit("st z+, r%s", acc[0]) + print "" + acc = acc[1:] + acc[:1] + lo_r = lo_r[1:] + lo_r[:1] # make the indexing easy + + emit("mul r%s, r%s", lo_r[0], hi_r[h - 1]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("st z+, r%s", acc[0]) + emit("st z+, r%s", acc[1]) + print "" + emit("sbiw r26, %s", init_size) # reset x + emit("sbiw r30, %s", size + init_size) # reset z + +# TODO you could do more rows of size 20 here if your integers are larger than 40 bytes + +s = size - init_size + +for i in xrange(s): + emit("ld r%s, x+", rg(i)) + +#### first few columns +# NOTE: this is only valid if size >= 3 +print "" +emit("ldi r23, 0") +emit("mul r%s, r%s", rg(0), rg(0)) +emit("st z+, r0") +emit("mov r22, r1") +print "" +emit("ldi r24, 0") +emit("mul r%s, r%s", rg(0), rg(1)) +emit("add r22, r0") +emit("adc r23, r1") +emit("adc r24, %s", zero) +emit("add r22, r0") +emit("adc r23, r1") +emit("adc r24, %s", zero) +emit("st z+, r22") +print "" +emit("ldi r22, 0") +emit("mul r%s, r%s", rg(0), rg(2)) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("mul r%s, r%s", rg(1), rg(1)) +emit("add r23, r0") +emit("adc r24, r1") +emit("adc r22, %s", zero) +emit("st z+, r23") +print "" + +acc = [23, 24, 22] +old_acc = [28, 29] +for i in xrange(3, s): + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", rg(0), rg(i)) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (i+1)//2): + emit("mul r%s, r%s", rg(j), rg(i-j)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word (if any) + if ((i+1) % 2) != 0: + emit("mul r%s, r%s", rg(i//2), rg(i//2)) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +regs = range(2, 22) +for i in xrange(init_size): + regs = regs[1:] + regs[:1] + emit("ld r%s, x+", regs[19]) + + for limit in [18, 19]: + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", regs[0], regs[limit]) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (limit+1)//2): + emit("mul r%s, r%s", regs[j], regs[limit-j]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + emit("ld r0, z") # load stored value from initial block, and add to accumulator (note z does not increment) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r25", acc[1]) + emit("adc r%s, r25", acc[2]) + + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word + if limit == 18: + emit("mul r%s, r%s", regs[9], regs[9]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +for i in xrange(1, s-3): + emit("ldi r%s, 0", old_acc[1]) + tmp = [acc[1], acc[2]] + acc = [acc[0], old_acc[0], old_acc[1]] + old_acc = tmp + + # gather non-equal words + emit("mul r%s, r%s", regs[i], regs[s - 1]) + emit("mov r%s, r0", acc[0]) + emit("mov r%s, r1", acc[1]) + for j in xrange(1, (s-i)//2): + emit("mul r%s, r%s", regs[i+j], regs[s - 1 - j]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + # multiply by 2 + emit("lsl r%s", acc[0]) + emit("rol r%s", acc[1]) + emit("rol r%s", acc[2]) + + # add equal word (if any) + if ((s-i) % 2) != 0: + emit("mul r%s, r%s", regs[i + (s-i)//2], regs[i + (s-i)//2]) + emit("add r%s, r0", acc[0]) + emit("adc r%s, r1", acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # add old accumulator + emit("add r%s, r%s", acc[0], old_acc[0]) + emit("adc r%s, r%s", acc[1], old_acc[1]) + emit("adc r%s, %s", acc[2], zero) + + # store + emit("st z+, r%s", acc[0]) + print "" + +acc = acc[1:] + acc[:1] +emit("ldi r%s, 0", acc[2]) +emit("mul r%s, r%s", regs[17], regs[19]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("mul r%s, r%s", regs[18], regs[18]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("st z+, r%s", acc[0]) +print "" + +acc = acc[1:] + acc[:1] +emit("ldi r%s, 0", acc[2]) +emit("mul r%s, r%s", regs[18], regs[19]) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("add r%s, r0", acc[0]) +emit("adc r%s, r1", acc[1]) +emit("adc r%s, %s", acc[2], zero) +emit("st z+, r%s", acc[0]) +print "" + +emit("mul r%s, r%s", regs[19], regs[19]) +emit("add r%s, r0", acc[1]) +emit("adc r%s, r1", acc[2]) +emit("st z+, r%s", acc[1]) + +emit("st z+, r%s", acc[2]) +emit("eor r1, r1") diff --git a/core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c b/core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c new file mode 100644 index 000000000..1e902b266 --- /dev/null +++ b/core/embed/ble_firmware/uecc/test/ecdsa_test_vectors.c @@ -0,0 +1,128 @@ +/* Copyright 2020, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include +#include +#include + +typedef struct { + const char* private_key; + const char* public_key; + const char* k; + const char* hash; + const char* r; + const char* s; +} Test; + +Test secp256k1_tests[] = { + { + "ebb2c082fd7727890a28ac82f6bdf97bad8de9f5d7c9028692de1a255cad3e0f", + "779dd197a5df977ed2cf6cb31d82d43328b790dc6b3b7d4437a427bd5847dfcde94b724a555b6d017bb7607c3e3281daf5b1699d6ef4124975c9237b917d426f", + "49a0d7b786ec9cde0d0721d72804befd06571c974b191efb42ecf322ba9ddd9a", + "4b688df40bcedbe641ddb16ff0a1842d9c67ea1c3bf63f3e0471baa664531d1a", + "241097efbf8b63bf145c8961dbdf10c310efbb3b2676bbc0f8b08505c9e2f795", + "021006b7838609339e8b415a7f9acb1b661828131aef1ecbc7955dfb01f3ca0e" + }, +}; + +extern int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *k, + uint8_t *signature, + uECC_Curve curve); + + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i +#include +#include + +typedef struct { + const char* k; + const char* Q; + int success; +} Test; + +Test secp160r1_tests[] = { + /* Note, I couldn't find any test vectors for secp160r1 online, so these are just + generated on my desktop using uECC. */ + { + "000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000002", + "02F997F33C5ED04C55D3EDF8675D3E92E8F46686F083A323482993E9440E817E21CFB7737DF8797B", + 1 + }, + { + "000000000000000000000000000000000000000003", + "7B76FF541EF363F2DF13DE1650BD48DAA958BC59C915CA790D8C8877B55BE0079D12854FFE9F6F5A", + 1 + }, + { /* n - 4 */ + "0100000000000000000001F4C8F927AED3CA752253", + "B4041D8683BE99F0AFE01C307B1AD4C100CF2A88C0CD35127BE0F73FF99F338B350B5A42864112F7", + 1 + }, + { /* n - 3 */ + "0100000000000000000001F4C8F927AED3CA752254", + "7B76FF541EF363F2DF13DE1650BD48DAA958BC5936EA3586F27377884AA41FF862ED7AAF816090A5", + 1 + }, + { /* n - 2 */ + "0100000000000000000001F4C8F927AED3CA752255", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { /* n - 1 */ + "0100000000000000000001F4C8F927AED3CA752256", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { /* n */ + "0100000000000000000001F4C8F927AED3CA752257", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + + +Test secp192r1_tests[] = { + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "000000000000000000000000000000000000000000000001", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF101207192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + 0 + }, + { + "000000000000000000000000000000000000000000000002", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB", + 1 + }, + { + "000000000000000000000000000000000000000000000003", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282D", + "35433907297CC378B0015703374729D7A4FE46647084E4BA5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282E", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D2282F", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp224r1_tests[] = { + { + "00000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "00000000000000000000000000000000000000000000000000000001", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + 0 + }, + { + "00000000000000000000000000000000000000000000000000000002", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA61C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB", + 1 + }, + { + "00000000000000000000000000000000000000000000000000000003", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A39", + "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3A", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D045C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3B", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3C", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D2142C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp256r1_tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000001", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000002", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC4766997807775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1", + 1 + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032", + 1 + }, + { /* n - 4 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254D", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B0308521F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739", + 1 + }, + { /* n - 3 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254E", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD", + 1 + }, + { /* n - 2 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E", + 0 + }, + { /* n - 1 */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632550", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A", + 0 + }, + { /* n */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + +Test secp256k1_tests[] = { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000001", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + 0 + }, + { + "0000000000000000000000000000000000000000000000000000000000000002", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE51AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A", + 1 + }, + { + "0000000000000000000000000000000000000000000000000000000000000003", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672", + 1 + }, + { /* n - 4 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413D", + "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D", + 1 + }, + { /* n - 3 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413E", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD", + 1 + }, + { /* n - 2 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD036413F", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705", + 0 + }, + { /* n - 1 */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777", + 0 + }, + { /* n */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + 0 + }, +}; + + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i +#include + +#ifndef uECC_TEST_NUMBER_OF_ITERATIONS +#define uECC_TEST_NUMBER_OF_ITERATIONS 256 +#endif + +void vli_print(char *str, uint8_t *vli, unsigned int size) { + printf("%s ", str); + for(unsigned i=0; i +#include + +void vli_print(char *str, uint8_t *vli, unsigned int size) { + printf("%s ", str); + for(unsigned i=0; i +#include + +void vli_print(uint8_t *vli, unsigned int size) { + for(unsigned i=0; i +#include + +int main() { + int i, c; + uint8_t private[32] = {0}; + uint8_t public[64] = {0}; + uint8_t hash[32] = {0}; + uint8_t sig[64] = {0}; + + const struct uECC_Curve_t * curves[5]; + int num_curves = 0; +#if uECC_SUPPORTS_secp160r1 + curves[num_curves++] = uECC_secp160r1(); +#endif +#if uECC_SUPPORTS_secp192r1 + curves[num_curves++] = uECC_secp192r1(); +#endif +#if uECC_SUPPORTS_secp224r1 + curves[num_curves++] = uECC_secp224r1(); +#endif +#if uECC_SUPPORTS_secp256r1 + curves[num_curves++] = uECC_secp256r1(); +#endif +#if uECC_SUPPORTS_secp256k1 + curves[num_curves++] = uECC_secp256k1(); +#endif + + printf("Testing 256 signatures\n"); + for (c = 0; c < num_curves; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + return 1; + } + memcpy(hash, public, sizeof(hash)); + + if (!uECC_sign(private, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_sign() failed\n"); + return 1; + } + + if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_verify() failed\n"); + return 1; + } + } + printf("\n"); + } + + return 0; +} diff --git a/core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example b/core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example new file mode 100644 index 000000000..df9aa101f --- /dev/null +++ b/core/embed/ble_firmware/uecc/test/test_ecdsa_deterministic.c.example @@ -0,0 +1,93 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" + +#include +#include + +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 + +typedef struct SHA256_CTX { + uint32_t state[8]; + uint64_t bitcount; + uint8_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; + +extern void SHA256_Init(SHA256_CTX *ctx); +extern void SHA256_Update(SHA256_CTX *ctx, const uint8_t *message, size_t message_size); +extern void SHA256_Final(uint8_t digest[SHA256_DIGEST_LENGTH], SHA256_CTX *ctx); + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +static void init_SHA256(const uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +static void update_SHA256(const uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +static void finish_SHA256(const uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +int main() { + int i, c; + uint8_t private[32] = {0}; + uint8_t public[64] = {0}; + uint8_t hash[32] = {0}; + uint8_t sig[64] = {0}; + + uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_BLOCK_LENGTH]; + SHA256_HashContext ctx = {{ + &init_SHA256, + &update_SHA256, + &finish_SHA256, + SHA256_BLOCK_LENGTH, + SHA256_DIGEST_LENGTH, + tmp + }}; + + const struct uECC_Curve_t * curves[5]; + curves[0] = uECC_secp160r1(); + curves[1] = uECC_secp192r1(); + curves[2] = uECC_secp224r1(); + curves[3] = uECC_secp256r1(); + curves[4] = uECC_secp256k1(); + + printf("Testing 256 signatures\n"); + for (c = 0; c < 5; ++c) { + for (i = 0; i < 256; ++i) { + printf("."); + fflush(stdout); + + if (!uECC_make_key(public, private, curves[c])) { + printf("uECC_make_key() failed\n"); + return 1; + } + memcpy(hash, public, sizeof(hash)); + + if (!uECC_sign_deterministic(private, hash, sizeof(hash), &ctx.uECC, sig, curves[c])) { + printf("uECC_sign() failed\n"); + return 1; + } + + if (!uECC_verify(public, hash, sizeof(hash), sig, curves[c])) { + printf("uECC_verify() failed\n"); + return 1; + } + } + printf("\n"); + } + + return 0; +} diff --git a/core/embed/ble_firmware/uecc/types.h b/core/embed/ble_firmware/uecc/types.h new file mode 100644 index 000000000..9ee81438f --- /dev/null +++ b/core/embed/ble_firmware/uecc/types.h @@ -0,0 +1,108 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_TYPES_H_ +#define _UECC_TYPES_H_ + +#ifndef uECC_PLATFORM + #if __AVR__ + #define uECC_PLATFORM uECC_avr + #elif defined(__thumb2__) || defined(_M_ARMT) /* I think MSVC only supports Thumb-2 targets */ + #define uECC_PLATFORM uECC_arm_thumb2 + #elif defined(__thumb__) + #define uECC_PLATFORM uECC_arm_thumb + #elif defined(__arm__) || defined(_M_ARM) + #define uECC_PLATFORM uECC_arm + #elif defined(__aarch64__) + #define uECC_PLATFORM uECC_arm64 + #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__) + #define uECC_PLATFORM uECC_x86 + #elif defined(__amd64__) || defined(_M_X64) + #define uECC_PLATFORM uECC_x86_64 + #else + #define uECC_PLATFORM uECC_arch_other + #endif +#endif + +#ifndef uECC_ARM_USE_UMAAL + #if (uECC_PLATFORM == uECC_arm) && (__ARM_ARCH >= 6) + #define uECC_ARM_USE_UMAAL 1 + #elif (uECC_PLATFORM == uECC_arm_thumb2) && (__ARM_ARCH >= 6) && !__ARM_ARCH_7M__ + #define uECC_ARM_USE_UMAAL 1 + #else + #define uECC_ARM_USE_UMAAL 0 + #endif +#endif + +#ifndef uECC_WORD_SIZE + #if uECC_PLATFORM == uECC_avr + #define uECC_WORD_SIZE 1 + #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64) + #define uECC_WORD_SIZE 8 + #else + #define uECC_WORD_SIZE 4 + #endif +#endif + +#if (uECC_WORD_SIZE != 1) && (uECC_WORD_SIZE != 4) && (uECC_WORD_SIZE != 8) + #error "Unsupported value for uECC_WORD_SIZE" +#endif + +#if ((uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1)) + #pragma message ("uECC_WORD_SIZE must be 1 for AVR") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 1 +#endif + +#if ((uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ + uECC_PLATFORM == uECC_arm_thumb2) && \ + (uECC_WORD_SIZE != 4)) + #pragma message ("uECC_WORD_SIZE must be 4 for ARM") + #undef uECC_WORD_SIZE + #define uECC_WORD_SIZE 4 +#endif + +#if defined(__SIZEOF_INT128__) || ((__clang_major__ * 100 + __clang_minor__) >= 302) + #define SUPPORTS_INT128 1 +#else + #define SUPPORTS_INT128 0 +#endif + +typedef int8_t wordcount_t; +typedef int16_t bitcount_t; +typedef int8_t cmpresult_t; + +#if (uECC_WORD_SIZE == 1) + +typedef uint8_t uECC_word_t; +typedef uint16_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80 +#define uECC_WORD_BITS 8 +#define uECC_WORD_BITS_SHIFT 3 +#define uECC_WORD_BITS_MASK 0x07 + +#elif (uECC_WORD_SIZE == 4) + +typedef uint32_t uECC_word_t; +typedef uint64_t uECC_dword_t; + +#define HIGH_BIT_SET 0x80000000 +#define uECC_WORD_BITS 32 +#define uECC_WORD_BITS_SHIFT 5 +#define uECC_WORD_BITS_MASK 0x01F + +#elif (uECC_WORD_SIZE == 8) + +typedef uint64_t uECC_word_t; +#if SUPPORTS_INT128 +typedef unsigned __int128 uECC_dword_t; +#endif + +#define HIGH_BIT_SET 0x8000000000000000ull +#define uECC_WORD_BITS 64 +#define uECC_WORD_BITS_SHIFT 6 +#define uECC_WORD_BITS_MASK 0x03F + +#endif /* uECC_WORD_SIZE */ + +#endif /* _UECC_TYPES_H_ */ diff --git a/core/embed/ble_firmware/uecc/uECC.c b/core/embed/ble_firmware/uecc/uECC.c new file mode 100644 index 000000000..a3d502cf2 --- /dev/null +++ b/core/embed/ble_firmware/uecc/uECC.c @@ -0,0 +1,1669 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#include "uECC.h" +#include "uECC_vli.h" + +#ifndef uECC_RNG_MAX_TRIES + #define uECC_RNG_MAX_TRIES 64 +#endif + +#if uECC_ENABLE_VLI_API + #define uECC_VLI_API +#else + #define uECC_VLI_API static +#endif + +#if (uECC_PLATFORM == uECC_avr) || \ + (uECC_PLATFORM == uECC_arm) || \ + (uECC_PLATFORM == uECC_arm_thumb) || \ + (uECC_PLATFORM == uECC_arm_thumb2) + #define CONCATX(a, ...) a ## __VA_ARGS__ + #define CONCAT(a, ...) CONCATX(a, __VA_ARGS__) + + #define STRX(a) #a + #define STR(a) STRX(a) + + #define EVAL(...) EVAL1(EVAL1(EVAL1(EVAL1(__VA_ARGS__)))) + #define EVAL1(...) EVAL2(EVAL2(EVAL2(EVAL2(__VA_ARGS__)))) + #define EVAL2(...) EVAL3(EVAL3(EVAL3(EVAL3(__VA_ARGS__)))) + #define EVAL3(...) EVAL4(EVAL4(EVAL4(EVAL4(__VA_ARGS__)))) + #define EVAL4(...) __VA_ARGS__ + + #define DEC_1 0 + #define DEC_2 1 + #define DEC_3 2 + #define DEC_4 3 + #define DEC_5 4 + #define DEC_6 5 + #define DEC_7 6 + #define DEC_8 7 + #define DEC_9 8 + #define DEC_10 9 + #define DEC_11 10 + #define DEC_12 11 + #define DEC_13 12 + #define DEC_14 13 + #define DEC_15 14 + #define DEC_16 15 + #define DEC_17 16 + #define DEC_18 17 + #define DEC_19 18 + #define DEC_20 19 + #define DEC_21 20 + #define DEC_22 21 + #define DEC_23 22 + #define DEC_24 23 + #define DEC_25 24 + #define DEC_26 25 + #define DEC_27 26 + #define DEC_28 27 + #define DEC_29 28 + #define DEC_30 29 + #define DEC_31 30 + #define DEC_32 31 + + #define DEC(N) CONCAT(DEC_, N) + + #define SECOND_ARG(_, val, ...) val + #define SOME_CHECK_0 ~, 0 + #define GET_SECOND_ARG(...) SECOND_ARG(__VA_ARGS__, SOME,) + #define SOME_OR_0(N) GET_SECOND_ARG(CONCAT(SOME_CHECK_, N)) + + #define EMPTY(...) + #define DEFER(...) __VA_ARGS__ EMPTY() + + #define REPEAT_NAME_0() REPEAT_0 + #define REPEAT_NAME_SOME() REPEAT_SOME + #define REPEAT_0(...) + #define REPEAT_SOME(N, stuff) DEFER(CONCAT(REPEAT_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), stuff) stuff + #define REPEAT(N, stuff) EVAL(REPEAT_SOME(N, stuff)) + + #define REPEATM_NAME_0() REPEATM_0 + #define REPEATM_NAME_SOME() REPEATM_SOME + #define REPEATM_0(...) + #define REPEATM_SOME(N, macro) macro(N) \ + DEFER(CONCAT(REPEATM_NAME_, SOME_OR_0(DEC(N))))()(DEC(N), macro) + #define REPEATM(N, macro) EVAL(REPEATM_SOME(N, macro)) +#endif + +#include "platform-specific.inc" + +#if (uECC_WORD_SIZE == 1) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 21 /* Due to the size of curve_n. */ + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 24 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 28 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 32 + #endif +#elif (uECC_WORD_SIZE == 4) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 6 /* Due to the size of curve_n. */ + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 6 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 7 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 8 + #endif +#elif (uECC_WORD_SIZE == 8) + #if uECC_SUPPORTS_secp160r1 + #define uECC_MAX_WORDS 3 + #endif + #if uECC_SUPPORTS_secp192r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 3 + #endif + #if uECC_SUPPORTS_secp224r1 + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 4 + #endif + #if (uECC_SUPPORTS_secp256r1 || uECC_SUPPORTS_secp256k1) + #undef uECC_MAX_WORDS + #define uECC_MAX_WORDS 4 + #endif +#endif /* uECC_WORD_SIZE */ + +#define BITS_TO_WORDS(num_bits) ((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8)) +#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8) + +struct uECC_Curve_t { + wordcount_t num_words; + wordcount_t num_bytes; + bitcount_t num_n_bits; + uECC_word_t p[uECC_MAX_WORDS]; + uECC_word_t n[uECC_MAX_WORDS]; + uECC_word_t G[uECC_MAX_WORDS * 2]; + uECC_word_t b[uECC_MAX_WORDS]; + void (*double_jacobian)(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * Z1, + uECC_Curve curve); +#if uECC_SUPPORT_COMPRESSED_POINT + void (*mod_sqrt)(uECC_word_t *a, uECC_Curve curve); +#endif + void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve); +#if (uECC_OPTIMIZATION_LEVEL > 0) + void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product); +#endif +}; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN +static void bcopy(uint8_t *dst, + const uint8_t *src, + unsigned num_bytes) { + while (0 != num_bytes) { + num_bytes--; + dst[num_bytes] = src[num_bytes]; + } +} +#endif + +static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +#if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \ + uECC_PLATFORM == uECC_arm_thumb2) + #include "asm_arm.inc" +#endif + +#if (uECC_PLATFORM == uECC_avr) + #include "asm_avr.inc" +#endif + +#if default_RNG_defined +static uECC_RNG_Function g_rng_function = &default_RNG; +#else +static uECC_RNG_Function g_rng_function = 0; +#endif + +void uECC_set_rng(uECC_RNG_Function rng_function) { + g_rng_function = rng_function; +} + +uECC_RNG_Function uECC_get_rng(void) { + return g_rng_function; +} + +int uECC_curve_private_key_size(uECC_Curve curve) { + return BITS_TO_BYTES(curve->num_n_bits); +} + +int uECC_curve_public_key_size(uECC_Curve curve) { + return 2 * curve->num_bytes; +} + +#if !asm_clear +uECC_VLI_API void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + vli[i] = 0; + } +} +#endif /* !asm_clear */ + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words) { + uECC_word_t bits = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + bits |= vli[i]; + } + return (bits == 0); +} + +/* Returns nonzero if bit 'bit' of vli is set. */ +uECC_VLI_API uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit) { + return (vli[bit >> uECC_WORD_BITS_SHIFT] & ((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK))); +} + +/* Counts the number of words in vli. */ +static wordcount_t vli_numDigits(const uECC_word_t *vli, const wordcount_t max_words) { + wordcount_t i; + /* Search from the end until we find a non-zero digit. + We do it in reverse because we expect that most digits will be nonzero. */ + for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) { + } + + return (i + 1); +} + +/* Counts the number of bits required to represent vli. */ +uECC_VLI_API bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words) { + uECC_word_t i; + uECC_word_t digit; + + wordcount_t num_digits = vli_numDigits(vli, max_words); + if (num_digits == 0) { + return 0; + } + + digit = vli[num_digits - 1]; + for (i = 0; digit; ++i) { + digit >>= 1; + } + + return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i); +} + +/* Sets dest = src. */ +#if !asm_set +uECC_VLI_API void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) { + wordcount_t i; + for (i = 0; i < num_words; ++i) { + dest[i] = src[i]; + } +} +#endif /* !asm_set */ + +/* Returns sign of left - right. */ +static cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + if (left[i] > right[i]) { + return 1; + } else if (left[i] < right[i]) { + return -1; + } + } + return 0; +} + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise. */ +uECC_VLI_API uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t diff = 0; + wordcount_t i; + for (i = num_words - 1; i >= 0; --i) { + diff |= (left[i] ^ right[i]); + } + return (diff == 0); +} + +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Returns sign of left - right, in constant time. */ +uECC_VLI_API cmpresult_t uECC_vli_cmp(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words); + uECC_word_t equal = uECC_vli_isZero(tmp, num_words); + return (!equal - 2 * neg); +} + +/* Computes vli = vli >> 1. */ +#if !asm_rshift1 +uECC_VLI_API void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words) { + uECC_word_t *end = vli; + uECC_word_t carry = 0; + + vli += num_words; + while (vli-- > end) { + uECC_word_t temp = *vli; + *vli = (temp >> 1) | carry; + carry = temp << (uECC_WORD_BITS - 1); + } +} +#endif /* !asm_rshift1 */ + +/* Computes result = left + right, returning carry. Can modify in place. */ +#if !asm_add +uECC_VLI_API uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t carry = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t sum = left[i] + right[i] + carry; + if (sum != left[i]) { + carry = (sum < left[i]); + } + result[i] = sum; + } + return carry; +} +#endif /* !asm_add */ + +/* Computes result = left - right, returning borrow. Can modify in place. */ +#if !asm_sub +uECC_VLI_API uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words; ++i) { + uECC_word_t diff = left[i] - right[i] - borrow; + if (diff != left[i]) { + borrow = (diff > left[i]); + } + result[i] = diff; + } + return borrow; +} +#endif /* !asm_sub */ + +#if !asm_mult || (uECC_SQUARE_FUNC && !asm_square) || \ + (uECC_SUPPORTS_secp256k1 && (uECC_OPTIMIZATION_LEVEL > 0) && \ + ((uECC_WORD_SIZE == 1) || (uECC_WORD_SIZE == 8))) +static void muladd(uECC_word_t a, + uECC_word_t b, + uECC_word_t *r0, + uECC_word_t *r1, + uECC_word_t *r2) { +#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128 + uint64_t a0 = a & 0xffffffffull; + uint64_t a1 = a >> 32; + uint64_t b0 = b & 0xffffffffull; + uint64_t b1 = b >> 32; + + uint64_t i0 = a0 * b0; + uint64_t i1 = a0 * b1; + uint64_t i2 = a1 * b0; + uint64_t i3 = a1 * b1; + + uint64_t p0, p1; + + i2 += (i0 >> 32); + i2 += i1; + if (i2 < i1) { /* overflow */ + i3 += 0x100000000ull; + } + + p0 = (i0 & 0xffffffffull) | (i2 << 32); + p1 = i3 + (i2 >> 32); + + *r0 += p0; + *r1 += (p1 + (*r0 < p0)); + *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0)); +#else + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; +#endif +} +#endif /* muladd needed */ + +#if !asm_mult +uECC_VLI_API void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + wordcount_t i, k; + + /* Compute each digit of result in sequence, maintaining the carries. */ + for (k = 0; k < num_words; ++k) { + for (i = 0; i <= k; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + for (k = num_words; k < num_words * 2 - 1; ++k) { + for (i = (k + 1) - num_words; i < num_words; ++i) { + muladd(left[i], right[k - i], &r0, &r1, &r2); + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + result[num_words * 2 - 1] = r0; +} +#endif /* !asm_mult */ + +#if uECC_SQUARE_FUNC + +#if !asm_square +static void mul2add(uECC_word_t a, + uECC_word_t b, + uECC_word_t *r0, + uECC_word_t *r1, + uECC_word_t *r2) { +#if uECC_WORD_SIZE == 8 && !SUPPORTS_INT128 + uint64_t a0 = a & 0xffffffffull; + uint64_t a1 = a >> 32; + uint64_t b0 = b & 0xffffffffull; + uint64_t b1 = b >> 32; + + uint64_t i0 = a0 * b0; + uint64_t i1 = a0 * b1; + uint64_t i2 = a1 * b0; + uint64_t i3 = a1 * b1; + + uint64_t p0, p1; + + i2 += (i0 >> 32); + i2 += i1; + if (i2 < i1) + { /* overflow */ + i3 += 0x100000000ull; + } + + p0 = (i0 & 0xffffffffull) | (i2 << 32); + p1 = i3 + (i2 >> 32); + + *r2 += (p1 >> 63); + p1 = (p1 << 1) | (p0 >> 63); + p0 <<= 1; + + *r0 += p0; + *r1 += (p1 + (*r0 < p0)); + *r2 += ((*r1 < p1) || (*r1 == p1 && *r0 < p0)); +#else + uECC_dword_t p = (uECC_dword_t)a * b; + uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0; + *r2 += (p >> (uECC_WORD_BITS * 2 - 1)); + p *= 2; + r01 += p; + *r2 += (r01 < p); + *r1 = r01 >> uECC_WORD_BITS; + *r0 = (uECC_word_t)r01; +#endif +} + +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + uECC_word_t r0 = 0; + uECC_word_t r1 = 0; + uECC_word_t r2 = 0; + + wordcount_t i, k; + + for (k = 0; k < num_words * 2 - 1; ++k) { + uECC_word_t min = (k < num_words ? 0 : (k + 1) - num_words); + for (i = min; i <= k && i <= k - i; ++i) { + if (i < k-i) { + mul2add(left[i], left[k - i], &r0, &r1, &r2); + } else { + muladd(left[i], left[k - i], &r0, &r1, &r2); + } + } + result[k] = r0; + r0 = r1; + r1 = r2; + r2 = 0; + } + + result[num_words * 2 - 1] = r0; +} +#endif /* !asm_square */ + +#else /* uECC_SQUARE_FUNC */ + +#if uECC_ENABLE_VLI_API +uECC_VLI_API void uECC_vli_square(uECC_word_t *result, + const uECC_word_t *left, + wordcount_t num_words) { + uECC_vli_mult(result, left, left, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +#endif /* uECC_SQUARE_FUNC */ + +/* Computes result = (left + right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modAdd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = uECC_vli_add(result, left, right, num_words); + if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) { + /* result > mod (result = mod + remainder), so subtract mod to get remainder. */ + uECC_vli_sub(result, result, mod, num_words); + } +} + +/* Computes result = (left - right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +uECC_VLI_API void uECC_vli_modSub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words); + if (l_borrow) { + /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x, + we can get the correct result from result + mod (with overflow). */ + uECC_vli_add(result, result, mod, num_words); + } +} + +/* Computes result = product % mod, where product is 2N words long. */ +/* Currently only designed to work for curve_p or curve_n. */ +uECC_VLI_API void uECC_vli_mmod(uECC_word_t *result, + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t mod_multiple[2 * uECC_MAX_WORDS]; + uECC_word_t tmp[2 * uECC_MAX_WORDS]; + uECC_word_t *v[2] = {tmp, product}; + uECC_word_t index; + + /* Shift mod so its highest set bit is at the maximum position. */ + bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) - uECC_vli_numBits(mod, num_words); + wordcount_t word_shift = shift / uECC_WORD_BITS; + wordcount_t bit_shift = shift % uECC_WORD_BITS; + uECC_word_t carry = 0; + uECC_vli_clear(mod_multiple, word_shift); + if (bit_shift > 0) { + for(index = 0; index < (uECC_word_t)num_words; ++index) { + mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry; + carry = mod[index] >> (uECC_WORD_BITS - bit_shift); + } + } else { + uECC_vli_set(mod_multiple + word_shift, mod, num_words); + } + + for (index = 1; shift >= 0; --shift) { + uECC_word_t borrow = 0; + wordcount_t i; + for (i = 0; i < num_words * 2; ++i) { + uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow; + if (diff != v[index][i]) { + borrow = (diff > v[index][i]); + } + v[1 - index][i] = diff; + } + index = !(index ^ borrow); /* Swap the index if there was no borrow */ + uECC_vli_rshift1(mod_multiple, num_words); + mod_multiple[num_words - 1] |= mod_multiple[num_words] << (uECC_WORD_BITS - 1); + uECC_vli_rshift1(mod_multiple + num_words, num_words); + } + uECC_vli_set(result, v[index], num_words); +} + +/* Computes result = (left * right) % mod. */ +uECC_VLI_API void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} + +uECC_VLI_API void uECC_vli_modMult_fast(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + uECC_Curve curve) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_mult(product, left, right, curve->num_words); +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +#if uECC_SQUARE_FUNC + +#if uECC_ENABLE_VLI_API +/* Computes result = left^2 % mod. */ +uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_square(product, left, num_words); + uECC_vli_mmod(result, product, mod, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) { + uECC_word_t product[2 * uECC_MAX_WORDS]; + uECC_vli_square(product, left, curve->num_words); +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +#else /* uECC_SQUARE_FUNC */ + +#if uECC_ENABLE_VLI_API +uECC_VLI_API void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_vli_modMult(result, left, left, mod, num_words); +} +#endif /* uECC_ENABLE_VLI_API */ + +uECC_VLI_API void uECC_vli_modSquare_fast(uECC_word_t *result, + const uECC_word_t *left, + uECC_Curve curve) { + uECC_vli_modMult_fast(result, left, left, curve); +} + +#endif /* uECC_SQUARE_FUNC */ + +#define EVEN(vli) (!(vli[0] & 1)) +static void vli_modInv_update(uECC_word_t *uv, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t carry = 0; + if (!EVEN(uv)) { + carry = uECC_vli_add(uv, uv, mod, num_words); + } + uECC_vli_rshift1(uv, num_words); + if (carry) { + uv[num_words - 1] |= HIGH_BIT_SET; + } +} + +/* Computes result = (1 / input) % mod. All VLIs are the same size. + See "From Euclid's GCD to Montgomery Multiplication to the Great Divide" */ +uECC_VLI_API void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words) { + uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS]; + cmpresult_t cmpResult; + + if (uECC_vli_isZero(input, num_words)) { + uECC_vli_clear(result, num_words); + return; + } + + uECC_vli_set(a, input, num_words); + uECC_vli_set(b, mod, num_words); + uECC_vli_clear(u, num_words); + u[0] = 1; + uECC_vli_clear(v, num_words); + while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) { + if (EVEN(a)) { + uECC_vli_rshift1(a, num_words); + vli_modInv_update(u, mod, num_words); + } else if (EVEN(b)) { + uECC_vli_rshift1(b, num_words); + vli_modInv_update(v, mod, num_words); + } else if (cmpResult > 0) { + uECC_vli_sub(a, a, b, num_words); + uECC_vli_rshift1(a, num_words); + if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) { + uECC_vli_add(u, u, mod, num_words); + } + uECC_vli_sub(u, u, v, num_words); + vli_modInv_update(u, mod, num_words); + } else { + uECC_vli_sub(b, b, a, num_words); + uECC_vli_rshift1(b, num_words); + if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) { + uECC_vli_add(v, v, mod, num_words); + } + uECC_vli_sub(v, v, u, num_words); + vli_modInv_update(v, mod, num_words); + } + } + uECC_vli_set(result, u, num_words); +} + +/* ------ Point operations ------ */ + +#include "curve-specific.inc" + +/* Returns 1 if 'point' is the point at infinity, 0 otherwise. */ +#define EccPoint_isZero(point, curve) uECC_vli_isZero((point), (curve)->num_words * 2) + +/* Point multiplication algorithm using Montgomery's ladder with co-Z coordinates. +From http://eprint.iacr.org/2011/338.pdf +*/ + +/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */ +static void apply_z(uECC_word_t * X1, + uECC_word_t * Y1, + const uECC_word_t * const Z, + uECC_Curve curve) { + uECC_word_t t1[uECC_MAX_WORDS]; + + uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */ + uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */ + uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */ + uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */ +} + +/* P = (x1, y1) => 2P, (x2, y2) => P' */ +static void XYcZ_initial_double(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + const uECC_word_t * const initial_Z, + uECC_Curve curve) { + uECC_word_t z[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + if (initial_Z) { + uECC_vli_set(z, initial_Z, num_words); + } else { + uECC_vli_clear(z, num_words); + z[0] = 1; + } + + uECC_vli_set(X2, X1, num_words); + uECC_vli_set(Y2, Y1, num_words); + + apply_z(X1, Y1, z, curve); + curve->double_jacobian(X1, Y1, z, curve); + apply_z(X2, Y2, z, curve); +} + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) + or P => P', Q => P + Q +*/ +static void XYcZ_add(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */ + + uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */ + uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */ + uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */ + uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */ + + uECC_vli_set(X2, t5, num_words); +} + +/* Input P = (x1, y1, Z), Q = (x2, y2, Z) + Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3) + or P => P - Q, Q => P + Q +*/ +static void XYcZ_addC(uECC_word_t * X1, + uECC_word_t * Y1, + uECC_word_t * X2, + uECC_word_t * Y2, + uECC_Curve curve) { + /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */ + uECC_word_t t5[uECC_MAX_WORDS]; + uECC_word_t t6[uECC_MAX_WORDS]; + uECC_word_t t7[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */ + uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */ + uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */ + uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */ + uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */ + + uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */ + uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */ + uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */ + uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */ + uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */ + + uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */ + uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */ + uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = (y2 - y1)*(B - x3) - E = y3 */ + + uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */ + uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */ + uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */ + uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */ + uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words); /* t2 = (y2+y1)*(x3' - B) - E = y3' */ + + uECC_vli_set(X1, t7, num_words); +} + +/* result may overlap point. */ +static void EccPoint_mult(uECC_word_t * result, + const uECC_word_t * point, + const uECC_word_t * scalar, + const uECC_word_t * initial_Z, + bitcount_t num_bits, + uECC_Curve curve) { + /* R0 and R1 */ + uECC_word_t Rx[2][uECC_MAX_WORDS]; + uECC_word_t Ry[2][uECC_MAX_WORDS]; + uECC_word_t z[uECC_MAX_WORDS]; + bitcount_t i; + uECC_word_t nb; + wordcount_t num_words = curve->num_words; + + uECC_vli_set(Rx[1], point, num_words); + uECC_vli_set(Ry[1], point + num_words, num_words); + + XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve); + + for (i = num_bits - 2; i > 0; --i) { + nb = !uECC_vli_testBit(scalar, i); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + } + + nb = !uECC_vli_testBit(scalar, 0); + XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve); + + /* Find final 1/Z value. */ + uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */ + uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */ + uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */ + uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0)) */ + /* yP / (xP * Yb * (X1 - X0)) */ + uECC_vli_modMult_fast(z, z, point + num_words, curve); + uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve); /* Xb * yP / (xP * Yb * (X1 - X0)) */ + /* End 1/Z calculation */ + + XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve); + apply_z(Rx[0], Ry[0], z, curve); + + uECC_vli_set(result, Rx[0], num_words); + uECC_vli_set(result + num_words, Ry[0], num_words); +} + +static uECC_word_t regularize_k(const uECC_word_t * const k, + uECC_word_t *k0, + uECC_word_t *k1, + uECC_Curve curve) { + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) || + (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) && + uECC_vli_testBit(k0, num_n_bits)); + uECC_vli_add(k1, k0, curve->n, num_n_words); + return carry; +} + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +uECC_VLI_API int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words) { + uECC_word_t mask = (uECC_word_t)-1; + uECC_word_t tries; + bitcount_t num_bits = uECC_vli_numBits(top, num_words); + + if (!g_rng_function) { + return 0; + } + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) { + return 0; + } + random[num_words - 1] &= mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits)); + if (!uECC_vli_isZero(random, num_words) && + uECC_vli_cmp(top, random, num_words) == 1) { + return 1; + } + } + return 0; +} + +static uECC_word_t EccPoint_compute_public_key(uECC_word_t *result, + uECC_word_t *private_key, + uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(private_key, tmp1, tmp2, curve); + + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(p2[carry], curve->p, curve->num_words)) { + return 0; + } + initial_Z = p2[carry]; + } + EccPoint_mult(result, curve->G, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); + + if (EccPoint_isZero(result, curve)) { + return 0; + } + return 1; +} + +#if uECC_WORD_SIZE == 1 + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uint8_t *native) { + wordcount_t i; + for (i = 0; i < num_bytes; ++i) { + bytes[i] = native[(num_bytes - 1) - i]; + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uint8_t *native, + const uint8_t *bytes, + int num_bytes) { + uECC_vli_nativeToBytes(native, num_bytes, bytes); +} + +#else + +uECC_VLI_API void uECC_vli_nativeToBytes(uint8_t *bytes, + int num_bytes, + const uECC_word_t *native) { + int i; + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE)); + } +} + +uECC_VLI_API void uECC_vli_bytesToNative(uECC_word_t *native, + const uint8_t *bytes, + int num_bytes) { + int i; + uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE); + for (i = 0; i < num_bytes; ++i) { + unsigned b = num_bytes - 1 - i; + native[b / uECC_WORD_SIZE] |= + (uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE)); + } +} + +#endif /* uECC_WORD_SIZE */ + +int uECC_make_key(uint8_t *public_key, + uint8_t *private_key, + uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_private = (uECC_word_t *)private_key; + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _private[uECC_MAX_WORDS]; + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!uECC_generate_random_int(_private, curve->n, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (EccPoint_compute_public_key(_public, _private, curve)) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(private_key, BITS_TO_BYTES(curve->num_n_bits), _private); + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words); +#endif + return 1; + } + } + return 0; +} + +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve) { + uECC_word_t _public[uECC_MAX_WORDS * 2]; + uECC_word_t _private[uECC_MAX_WORDS]; + + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {_private, tmp}; + uECC_word_t *initial_Z = 0; + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_bytes = curve->num_bytes; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) _private, private_key, num_bytes); + bcopy((uint8_t *) _public, public_key, num_bytes*2); +#else + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits)); + uECC_vli_bytesToNative(_public, public_key, num_bytes); + uECC_vli_bytesToNative(_public + num_words, public_key + num_bytes, num_bytes); +#endif + + /* Regularize the bitcount for the private key so that attackers cannot use a side channel + attack to learn the number of leading zeros. */ + carry = regularize_k(_private, _private, tmp, curve); + + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) { + return 0; + } + initial_Z = p2[carry]; + } + + EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1, curve); +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) secret, (uint8_t *) _public, num_bytes); +#else + uECC_vli_nativeToBytes(secret, num_bytes, _public); +#endif + return !EccPoint_isZero(_public, curve); +} + +#if uECC_SUPPORT_COMPRESSED_POINT +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve) { + wordcount_t i; + for (i = 0; i < curve->num_bytes; ++i) { + compressed[i+1] = public_key[i]; + } +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + compressed[0] = 2 + (public_key[curve->num_bytes] & 0x01); +#else + compressed[0] = 2 + (public_key[curve->num_bytes * 2 - 1] & 0x01); +#endif +} + +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *point = (uECC_word_t *)public_key; +#else + uECC_word_t point[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t *y = point + curve->num_words; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy(public_key, compressed+1, curve->num_bytes); +#else + uECC_vli_bytesToNative(point, compressed + 1, curve->num_bytes); +#endif + curve->x_side(y, point, curve); + curve->mod_sqrt(y, curve); + + if ((y[0] & 0x01) != (compressed[0] & 0x01)) { + uECC_vli_sub(y, curve->p, y, curve->num_words); + } + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, point); + uECC_vli_nativeToBytes(public_key + curve->num_bytes, curve->num_bytes, y); +#endif +} +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +uECC_VLI_API int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + + /* The point at infinity is invalid. */ + if (EccPoint_isZero(point, curve)) { + return 0; + } + + /* x and y must be smaller than p. */ + if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 || + uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) { + return 0; + } + + uECC_vli_modSquare_fast(tmp1, point + num_words, curve); + curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */ + + /* Make sure that y^2 == x^3 + ax + b */ + return (int)(uECC_vli_equal(tmp1, tmp2, num_words)); +} + +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + curve->num_words, public_key + curve->num_bytes, curve->num_bytes); +#endif + return uECC_valid_point(_public, curve); +} + +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve) { +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_private = (uECC_word_t *)private_key; + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _private[uECC_MAX_WORDS]; + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_bytesToNative(_private, private_key, BITS_TO_BYTES(curve->num_n_bits)); +#endif + + /* Make sure the private key is in the range [1, n-1]. */ + if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) { + return 0; + } + + /* Compute public key. */ + if (!EccPoint_compute_public_key(_public, _private, curve)) { + return 0; + } + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public); + uECC_vli_nativeToBytes( + public_key + curve->num_bytes, curve->num_bytes, _public + curve->num_words); +#endif + return 1; +} + + +/* -------- ECDSA code -------- */ + +static void bits2int(uECC_word_t *native, + const uint8_t *bits, + unsigned bits_size, + uECC_Curve curve) { + unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits); + unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits); + int shift; + uECC_word_t carry; + uECC_word_t *ptr; + + if (bits_size > num_n_bytes) { + bits_size = num_n_bytes; + } + + uECC_vli_clear(native, num_n_words); +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) native, bits, bits_size); +#else + uECC_vli_bytesToNative(native, bits, bits_size); +#endif + if (bits_size * 8 <= (unsigned)curve->num_n_bits) { + return; + } + shift = bits_size * 8 - curve->num_n_bits; + carry = 0; + ptr = native + num_n_words; + while (ptr-- > native) { + uECC_word_t temp = *ptr; + *ptr = (temp >> shift) | carry; + carry = temp << (uECC_WORD_BITS - shift); + } + + /* Reduce mod curve_n */ + if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) { + uECC_vli_sub(native, native, curve->n, num_n_words); + } +} + +static int uECC_sign_with_k_internal(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uECC_word_t *k, + uint8_t *signature, + uECC_Curve curve) { + + uECC_word_t tmp[uECC_MAX_WORDS]; + uECC_word_t s[uECC_MAX_WORDS]; + uECC_word_t *k2[2] = {tmp, s}; + uECC_word_t *initial_Z = 0; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *p = (uECC_word_t *)signature; +#else + uECC_word_t p[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t carry; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + + /* Make sure 0 < k < curve_n */ + if (uECC_vli_isZero(k, num_words) || uECC_vli_cmp(curve->n, k, num_n_words) != 1) { + return 0; + } + + carry = regularize_k(k, tmp, s, curve); + /* If an RNG function was specified, try to get a random initial Z value to improve + protection against side-channel attacks. */ + if (g_rng_function) { + if (!uECC_generate_random_int(k2[carry], curve->p, num_words)) { + return 0; + } + initial_Z = k2[carry]; + } + EccPoint_mult(p, curve->G, k2[!carry], initial_Z, num_n_bits + 1, curve); + if (uECC_vli_isZero(p, num_words)) { + return 0; + } + + /* If an RNG function was specified, get a random number + to prevent side channel analysis of k. */ + if (!g_rng_function) { + uECC_vli_clear(tmp, num_n_words); + tmp[0] = 1; + } else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) { + return 0; + } + + /* Prevent side channel analysis of uECC_vli_modInv() to determine + bits of k / the private key by premultiplying by a random number */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */ + uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */ + uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */ + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN == 0 + uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */ +#endif + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); +#else + uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits)); /* tmp = d */ +#endif + + s[num_n_words - 1] = 0; + uECC_vli_set(s, p, num_words); + uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */ + + bits2int(tmp, message_hash, hash_size, curve); + uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */ + uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */ + if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) { + return 0; + } +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) signature + curve->num_bytes, (uint8_t *) s, curve->num_bytes); +#else + uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s); +#endif + return 1; +} + +/* For testing - sign with an explicitly specified k value */ +int uECC_sign_with_k(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *k, + uint8_t *signature, + uECC_Curve curve) { + uECC_word_t k2[uECC_MAX_WORDS]; + bits2int(k2, k, BITS_TO_BYTES(curve->num_n_bits), curve); + return uECC_sign_with_k_internal(private_key, message_hash, hash_size, k2, signature, curve); +} + +int uECC_sign(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uint8_t *signature, + uECC_Curve curve) { + uECC_word_t k[uECC_MAX_WORDS]; + uECC_word_t tries; + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + if (!uECC_generate_random_int(k, curve->n, BITS_TO_WORDS(curve->num_n_bits))) { + return 0; + } + + if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, k, signature, curve)) { + return 1; + } + } + return 0; +} + +/* Compute an HMAC using K as a key (as in RFC 6979). Note that K is always + the same size as the hash result size. */ +static void HMAC_init(const uECC_HashContext *hash_context, const uint8_t *K) { + uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) + pad[i] = K[i] ^ 0x36; + for (; i < hash_context->block_size; ++i) + pad[i] = 0x36; + + hash_context->init_hash(hash_context); + hash_context->update_hash(hash_context, pad, hash_context->block_size); +} + +static void HMAC_update(const uECC_HashContext *hash_context, + const uint8_t *message, + unsigned message_size) { + hash_context->update_hash(hash_context, message, message_size); +} + +static void HMAC_finish(const uECC_HashContext *hash_context, + const uint8_t *K, + uint8_t *result) { + uint8_t *pad = hash_context->tmp + 2 * hash_context->result_size; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) + pad[i] = K[i] ^ 0x5c; + for (; i < hash_context->block_size; ++i) + pad[i] = 0x5c; + + hash_context->finish_hash(hash_context, result); + + hash_context->init_hash(hash_context); + hash_context->update_hash(hash_context, pad, hash_context->block_size); + hash_context->update_hash(hash_context, result, hash_context->result_size); + hash_context->finish_hash(hash_context, result); +} + +/* V = HMAC_K(V) */ +static void update_V(const uECC_HashContext *hash_context, uint8_t *K, uint8_t *V) { + HMAC_init(hash_context, K); + HMAC_update(hash_context, V, hash_context->result_size); + HMAC_finish(hash_context, K, V); +} + +/* Deterministic signing, similar to RFC 6979. Differences are: + * We just use H(m) directly rather than bits2octets(H(m)) + (it is not reduced modulo curve_n). + * We generate a value for k (aka T) directly rather than converting endianness. + + Layout of hash_context->tmp: | | (1 byte overlapped 0x00 or 0x01) / */ +int uECC_sign_deterministic(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uECC_HashContext *hash_context, + uint8_t *signature, + uECC_Curve curve) { + uint8_t *K = hash_context->tmp; + uint8_t *V = K + hash_context->result_size; + wordcount_t num_bytes = curve->num_bytes; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + bitcount_t num_n_bits = curve->num_n_bits; + uECC_word_t tries; + unsigned i; + for (i = 0; i < hash_context->result_size; ++i) { + V[i] = 0x01; + K[i] = 0; + } + + /* K = HMAC_K(V || 0x00 || int2octets(x) || h(m)) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x00; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_update(hash_context, private_key, num_bytes); + HMAC_update(hash_context, message_hash, hash_size); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + + /* K = HMAC_K(V || 0x01 || int2octets(x) || h(m)) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x01; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_update(hash_context, private_key, num_bytes); + HMAC_update(hash_context, message_hash, hash_size); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + + for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) { + uECC_word_t T[uECC_MAX_WORDS]; + uint8_t *T_ptr = (uint8_t *)T; + wordcount_t T_bytes = 0; + for (;;) { + update_V(hash_context, K, V); + for (i = 0; i < hash_context->result_size; ++i) { + T_ptr[T_bytes++] = V[i]; + if (T_bytes >= num_n_words * uECC_WORD_SIZE) { + goto filled; + } + } + } + filled: + if ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8 > num_n_bits) { + uECC_word_t mask = (uECC_word_t)-1; + T[num_n_words - 1] &= + mask >> ((bitcount_t)(num_n_words * uECC_WORD_SIZE * 8 - num_n_bits)); + } + + if (uECC_sign_with_k_internal(private_key, message_hash, hash_size, T, signature, curve)) { + return 1; + } + + /* K = HMAC_K(V || 0x00) */ + HMAC_init(hash_context, K); + V[hash_context->result_size] = 0x00; + HMAC_update(hash_context, V, hash_context->result_size + 1); + HMAC_finish(hash_context, K, K); + + update_V(hash_context, K, V); + } + return 0; +} + +static bitcount_t smax(bitcount_t a, bitcount_t b) { + return (a > b ? a : b); +} + +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve) { + uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS]; + uECC_word_t z[uECC_MAX_WORDS]; + uECC_word_t sum[uECC_MAX_WORDS * 2]; + uECC_word_t rx[uECC_MAX_WORDS]; + uECC_word_t ry[uECC_MAX_WORDS]; + uECC_word_t tx[uECC_MAX_WORDS]; + uECC_word_t ty[uECC_MAX_WORDS]; + uECC_word_t tz[uECC_MAX_WORDS]; + const uECC_word_t *points[4]; + const uECC_word_t *point; + bitcount_t num_bits; + bitcount_t i; +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + uECC_word_t *_public = (uECC_word_t *)public_key; +#else + uECC_word_t _public[uECC_MAX_WORDS * 2]; +#endif + uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS]; + wordcount_t num_words = curve->num_words; + wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits); + + rx[num_n_words - 1] = 0; + r[num_n_words - 1] = 0; + s[num_n_words - 1] = 0; + +#if uECC_VLI_NATIVE_LITTLE_ENDIAN + bcopy((uint8_t *) r, signature, curve->num_bytes); + bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes); +#else + uECC_vli_bytesToNative(_public, public_key, curve->num_bytes); + uECC_vli_bytesToNative( + _public + num_words, public_key + curve->num_bytes, curve->num_bytes); + uECC_vli_bytesToNative(r, signature, curve->num_bytes); + uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes); +#endif + + /* r, s must not be 0. */ + if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) { + return 0; + } + + /* r, s must be < n. */ + if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 || + uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) { + return 0; + } + + /* Calculate u1 and u2. */ + uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */ + u1[num_n_words - 1] = 0; + bits2int(u1, message_hash, hash_size, curve); + uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */ + uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */ + + /* Calculate sum = G + Q. */ + uECC_vli_set(sum, _public, num_words); + uECC_vli_set(sum + num_words, _public + num_words, num_words); + uECC_vli_set(tx, curve->G, num_words); + uECC_vli_set(ty, curve->G + num_words, num_words); + uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */ + XYcZ_add(tx, ty, sum, sum + num_words, curve); + uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */ + apply_z(sum, sum + num_words, z, curve); + + /* Use Shamir's trick to calculate u1*G + u2*Q */ + points[0] = 0; + points[1] = curve->G; + points[2] = _public; + points[3] = sum; + num_bits = smax(uECC_vli_numBits(u1, num_n_words), + uECC_vli_numBits(u2, num_n_words)); + + point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) | + ((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)]; + uECC_vli_set(rx, point, num_words); + uECC_vli_set(ry, point + num_words, num_words); + uECC_vli_clear(z, num_words); + z[0] = 1; + + for (i = num_bits - 2; i >= 0; --i) { + uECC_word_t index; + curve->double_jacobian(rx, ry, z, curve); + + index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1); + point = points[index]; + if (point) { + uECC_vli_set(tx, point, num_words); + uECC_vli_set(ty, point + num_words, num_words); + apply_z(tx, ty, z, curve); + uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */ + XYcZ_add(tx, ty, rx, ry, curve); + uECC_vli_modMult_fast(z, z, tz, curve); + } + } + + uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */ + apply_z(rx, ry, z, curve); + + /* v = x1 (mod n) */ + if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) { + uECC_vli_sub(rx, rx, curve->n, num_n_words); + } + + /* Accept only if v == r. */ + return (int)(uECC_vli_equal(rx, r, num_words)); +} + +#if uECC_ENABLE_VLI_API + +unsigned uECC_curve_num_words(uECC_Curve curve) { + return curve->num_words; +} + +unsigned uECC_curve_num_bytes(uECC_Curve curve) { + return curve->num_bytes; +} + +unsigned uECC_curve_num_bits(uECC_Curve curve) { + return curve->num_bytes * 8; +} + +unsigned uECC_curve_num_n_words(uECC_Curve curve) { + return BITS_TO_WORDS(curve->num_n_bits); +} + +unsigned uECC_curve_num_n_bytes(uECC_Curve curve) { + return BITS_TO_BYTES(curve->num_n_bits); +} + +unsigned uECC_curve_num_n_bits(uECC_Curve curve) { + return curve->num_n_bits; +} + +const uECC_word_t *uECC_curve_p(uECC_Curve curve) { + return curve->p; +} + +const uECC_word_t *uECC_curve_n(uECC_Curve curve) { + return curve->n; +} + +const uECC_word_t *uECC_curve_G(uECC_Curve curve) { + return curve->G; +} + +const uECC_word_t *uECC_curve_b(uECC_Curve curve) { + return curve->b; +} + +#if uECC_SUPPORT_COMPRESSED_POINT +void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve) { + curve->mod_sqrt(a, curve); +} +#endif + +void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve) { +#if (uECC_OPTIMIZATION_LEVEL > 0) + curve->mmod_fast(result, product); +#else + uECC_vli_mmod(result, product, curve->p, curve->num_words); +#endif +} + +void uECC_point_mult(uECC_word_t *result, + const uECC_word_t *point, + const uECC_word_t *scalar, + uECC_Curve curve) { + uECC_word_t tmp1[uECC_MAX_WORDS]; + uECC_word_t tmp2[uECC_MAX_WORDS]; + uECC_word_t *p2[2] = {tmp1, tmp2}; + uECC_word_t carry = regularize_k(scalar, tmp1, tmp2, curve); + + EccPoint_mult(result, point, p2[!carry], 0, curve->num_n_bits + 1, curve); +} + +#endif /* uECC_ENABLE_VLI_API */ diff --git a/core/embed/ble_firmware/uecc/uECC.h b/core/embed/ble_firmware/uecc/uECC.h new file mode 100644 index 000000000..dcbdbfa8b --- /dev/null +++ b/core/embed/ble_firmware/uecc/uECC.h @@ -0,0 +1,367 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_H_ +#define _UECC_H_ + +#include + +/* Platform selection options. +If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros. +Possible values for uECC_PLATFORM are defined below: */ +#define uECC_arch_other 0 +#define uECC_x86 1 +#define uECC_x86_64 2 +#define uECC_arm 3 +#define uECC_arm_thumb 4 +#define uECC_arm_thumb2 5 +#define uECC_arm64 6 +#define uECC_avr 7 + +/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes). +If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your +platform. */ + +/* Optimization level; trade speed for code size. + Larger values produce code that is faster but larger. + Currently supported values are 0 - 4; 0 is unusably slow for most applications. + Optimization level 4 currently only has an effect ARM platforms where more than one + curve is enabled. */ +#ifndef uECC_OPTIMIZATION_LEVEL + #define uECC_OPTIMIZATION_LEVEL 2 +#endif + +/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be +used for (scalar) squaring instead of the generic multiplication function. This can make things +faster somewhat faster, but increases the code size. */ +#ifndef uECC_SQUARE_FUNC + #define uECC_SQUARE_FUNC 0 +#endif + +/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native +little-endian format for *all* arrays passed in and out of the public API. This includes public +and private keys, shared secrets, signatures and message hashes. +Using this switch reduces the amount of call stack memory used by uECC, since less intermediate +translations are required. +Note that this will *only* work on native little-endian processors and it will treat the uint8_t +arrays passed into the public API as word arrays, therefore requiring the provided byte arrays +to be word aligned on architectures that do not support unaligned accesses. +IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible +with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use +the same endianness. */ +#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN + #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 +#endif + +/* Curve support selection. Set to 0 to remove that curve. */ +#ifndef uECC_SUPPORTS_secp160r1 + #define uECC_SUPPORTS_secp160r1 1 +#endif +#ifndef uECC_SUPPORTS_secp192r1 + #define uECC_SUPPORTS_secp192r1 1 +#endif +#ifndef uECC_SUPPORTS_secp224r1 + #define uECC_SUPPORTS_secp224r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256r1 + #define uECC_SUPPORTS_secp256r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256k1 + #define uECC_SUPPORTS_secp256k1 1 +#endif + +/* Specifies whether compressed point format is supported. + Set to 0 to disable point compression/decompression functions. */ +#ifndef uECC_SUPPORT_COMPRESSED_POINT + #define uECC_SUPPORT_COMPRESSED_POINT 1 +#endif + +struct uECC_Curve_t; +typedef const struct uECC_Curve_t * uECC_Curve; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if uECC_SUPPORTS_secp160r1 +uECC_Curve uECC_secp160r1(void); +#endif +#if uECC_SUPPORTS_secp192r1 +uECC_Curve uECC_secp192r1(void); +#endif +#if uECC_SUPPORTS_secp224r1 +uECC_Curve uECC_secp224r1(void); +#endif +#if uECC_SUPPORTS_secp256r1 +uECC_Curve uECC_secp256r1(void); +#endif +#if uECC_SUPPORTS_secp256k1 +uECC_Curve uECC_secp256k1(void); +#endif + +/* uECC_RNG_Function type +The RNG function should fill 'size' random bytes into 'dest'. It should return 1 if +'dest' was filled with random data, or 0 if the random data could not be generated. +The filled-in values should be either truly random, or from a cryptographically-secure PRNG. + +A correctly functioning RNG function must be set (using uECC_set_rng()) before calling +uECC_make_key() or uECC_sign(). + +Setting a correctly functioning RNG function improves the resistance to side-channel attacks +for uECC_shared_secret() and uECC_sign_deterministic(). + +A correct RNG function is set by default when building for Windows, Linux, or OS X. +If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom, +you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined +RNG function; you must provide your own. +*/ +typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size); + +/* uECC_set_rng() function. +Set the function that will be used to generate random bytes. The RNG function should +return 1 if the random data was generated, or 0 if the random data could not be generated. + +On platforms where there is no predefined RNG function (eg embedded platforms), this must +be called before uECC_make_key() or uECC_sign() are used. + +Inputs: + rng_function - The function that will be used to generate random bytes. +*/ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* uECC_get_rng() function. + +Returns the function that will be used to generate random bytes. +*/ +uECC_RNG_Function uECC_get_rng(void); + +/* uECC_curve_private_key_size() function. + +Returns the size of a private key for the curve in bytes. +*/ +int uECC_curve_private_key_size(uECC_Curve curve); + +/* uECC_curve_public_key_size() function. + +Returns the size of a public key for the curve in bytes. +*/ +int uECC_curve_public_key_size(uECC_Curve curve); + +/* uECC_make_key() function. +Create a public/private key pair. + +Outputs: + public_key - Will be filled in with the public key. Must be at least 2 * the curve size + (in bytes) long. For example, if the curve is secp256r1, public_key must be 64 + bytes long. + private_key - Will be filled in with the private key. Must be as long as the curve order; this + is typically the same as the curve size, except for secp160r1. For example, if the + curve is secp256r1, private_key must be 32 bytes long. + + For secp160r1, private_key must be 21 bytes long! Note that the first byte will + almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero). + +Returns 1 if the key pair was generated successfully, 0 if an error occurred. +*/ +int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); + +/* uECC_shared_secret() function. +Compute a shared secret given your secret key and someone else's public key. If the public key +is not from a trusted source and has not been previously verified, you should verify it first +using uECC_valid_public_key(). +Note: It is recommended that you hash the result of uECC_shared_secret() before using it for +symmetric encryption or HMAC. + +Inputs: + public_key - The public key of the remote party. + private_key - Your private key. + +Outputs: + secret - Will be filled in with the shared secret value. Must be the same size as the + curve size; for example, if the curve is secp256r1, secret must be 32 bytes long. + +Returns 1 if the shared secret was generated successfully, 0 if an error occurred. +*/ +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve); + +#if uECC_SUPPORT_COMPRESSED_POINT +/* uECC_compress() function. +Compress a public key. + +Inputs: + public_key - The public key to compress. + +Outputs: + compressed - Will be filled in with the compressed public key. Must be at least + (curve size + 1) bytes long; for example, if the curve is secp256r1, + compressed must be 33 bytes long. +*/ +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve); + +/* uECC_decompress() function. +Decompress a compressed public key. + +Inputs: + compressed - The compressed public key. + +Outputs: + public_key - Will be filled in with the decompressed public key. +*/ +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve); +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +/* uECC_valid_public_key() function. +Check to see if a public key is valid. + +Note that you are not required to check for a valid public key before using any other uECC +functions. However, you may wish to avoid spending CPU time computing a shared secret or +verifying a signature using an invalid public key. + +Inputs: + public_key - The public key to check. + +Returns 1 if the public key is valid, 0 if it is invalid. +*/ +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); + +/* uECC_compute_public_key() function. +Compute the corresponding public key for a private key. + +Inputs: + private_key - The private key to compute the public key for + +Outputs: + public_key - Will be filled in with the corresponding public key + +Returns 1 if the key was computed successfully, 0 if an error occurred. +*/ +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve); + +/* uECC_sign() function. +Generate an ECDSA signature for a given hash value. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + +Outputs: + signature - Will be filled in with the signature value. Must be at least 2 * curve size long. + For example, if the curve is secp256r1, signature must be 64 bytes long. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_HashContext structure. +This is used to pass in an arbitrary hash function to uECC_sign_deterministic(). +The structure will be used for multiple hash computations; each time a new hash +is computed, init_hash() will be called, followed by one or more calls to +update_hash(), and finally a call to finish_hash() to produce the resulting hash. + +The intention is that you will create a structure that includes uECC_HashContext +followed by any hash-specific data. For example: + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +void init_SHA256(uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +void update_SHA256(uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +... when signing ... +{ + uint8_t tmp[32 + 32 + 64]; + SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}}; + uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature); +} +*/ +typedef struct uECC_HashContext { + void (*init_hash)(const struct uECC_HashContext *context); + void (*update_hash)(const struct uECC_HashContext *context, + const uint8_t *message, + unsigned message_size); + void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result); + unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */ + unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */ + uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */ +} uECC_HashContext; + +/* uECC_sign_deterministic() function. +Generate an ECDSA signature for a given hash value, using a deterministic algorithm +(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling +this function; however, if the RNG is defined it will improve resistance to side-channel +attacks. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to +this function along with your private key and a hash context. Note that the message_hash +does not need to be computed with the same hash function used by hash_context. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + hash_context - A hash context to use. + +Outputs: + signature - Will be filled in with the signature value. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign_deterministic(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uECC_HashContext *hash_context, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_verify() function. +Verify an ECDSA signature. + +Usage: Compute the hash of the signed data using the same hash as the signer and +pass it to this function along with the signer's public key and the signature values (r and s). + +Inputs: + public_key - The signer's public key. + message_hash - The hash of the signed data. + hash_size - The size of message_hash in bytes. + signature - The signature value. + +Returns 1 if the signature is valid, 0 if it is invalid. +*/ +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _UECC_H_ */ diff --git a/core/embed/ble_firmware/uecc/uECC_vli.h b/core/embed/ble_firmware/uecc/uECC_vli.h new file mode 100644 index 000000000..864cc3335 --- /dev/null +++ b/core/embed/ble_firmware/uecc/uECC_vli.h @@ -0,0 +1,172 @@ +/* Copyright 2015, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_VLI_H_ +#define _UECC_VLI_H_ + +#include "uECC.h" +#include "types.h" + +/* Functions for raw large-integer manipulation. These are only available + if uECC.c is compiled with uECC_ENABLE_VLI_API defined to 1. */ +#ifndef uECC_ENABLE_VLI_API + #define uECC_ENABLE_VLI_API 0 +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if uECC_ENABLE_VLI_API + +void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words); + +/* Constant-time comparison to zero - secure way to compare long integers */ +/* Returns 1 if vli == 0, 0 otherwise. */ +uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words); + +/* Returns nonzero if bit 'bit' of vli is set. */ +uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit); + +/* Counts the number of bits required to represent vli. */ +bitcount_t uECC_vli_numBits(const uECC_word_t *vli, const wordcount_t max_words); + +/* Sets dest = src. */ +void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words); + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns one if left == right, zero otherwise */ +uECC_word_t uECC_vli_equal(const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Constant-time comparison function - secure way to compare long integers */ +/* Returns sign of left - right, in constant time. */ +cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right, wordcount_t num_words); + +/* Computes vli = vli >> 1. */ +void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words); + +/* Computes result = left + right, returning carry. Can modify in place. */ +uECC_word_t uECC_vli_add(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left - right, returning borrow. Can modify in place. */ +uECC_word_t uECC_vli_sub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left * right. Result must be 2 * num_words long. */ +void uECC_vli_mult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + wordcount_t num_words); + +/* Computes result = left^2. Result must be 2 * num_words long. */ +void uECC_vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words); + +/* Computes result = (left + right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +void uECC_vli_modAdd(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = (left - right) % mod. + Assumes that left < mod and right < mod, and that result does not overlap mod. */ +void uECC_vli_modSub(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = product % mod, where product is 2N words long. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_mmod(uECC_word_t *result, + uECC_word_t *product, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Calculates result = product (mod curve->p), where product is up to + 2 * curve->num_words long. */ +void uECC_vli_mmod_fast(uECC_word_t *result, uECC_word_t *product, uECC_Curve curve); + +/* Computes result = (left * right) % mod. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_modMult(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = (left * right) % curve->p. */ +void uECC_vli_modMult_fast(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *right, + uECC_Curve curve); + +/* Computes result = left^2 % mod. + Currently only designed to work for mod == curve->p or curve_n. */ +void uECC_vli_modSquare(uECC_word_t *result, + const uECC_word_t *left, + const uECC_word_t *mod, + wordcount_t num_words); + +/* Computes result = left^2 % curve->p. */ +void uECC_vli_modSquare_fast(uECC_word_t *result, const uECC_word_t *left, uECC_Curve curve); + +/* Computes result = (1 / input) % mod.*/ +void uECC_vli_modInv(uECC_word_t *result, + const uECC_word_t *input, + const uECC_word_t *mod, + wordcount_t num_words); + +#if uECC_SUPPORT_COMPRESSED_POINT +/* Calculates a = sqrt(a) (mod curve->p) */ +void uECC_vli_mod_sqrt(uECC_word_t *a, uECC_Curve curve); +#endif + +/* Converts an integer in uECC native format to big-endian bytes. */ +void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes, const uECC_word_t *native); +/* Converts big-endian bytes to an integer in uECC native format. */ +void uECC_vli_bytesToNative(uECC_word_t *native, const uint8_t *bytes, int num_bytes); + +unsigned uECC_curve_num_words(uECC_Curve curve); +unsigned uECC_curve_num_bytes(uECC_Curve curve); +unsigned uECC_curve_num_bits(uECC_Curve curve); +unsigned uECC_curve_num_n_words(uECC_Curve curve); +unsigned uECC_curve_num_n_bytes(uECC_Curve curve); +unsigned uECC_curve_num_n_bits(uECC_Curve curve); + +const uECC_word_t *uECC_curve_p(uECC_Curve curve); +const uECC_word_t *uECC_curve_n(uECC_Curve curve); +const uECC_word_t *uECC_curve_G(uECC_Curve curve); +const uECC_word_t *uECC_curve_b(uECC_Curve curve); + +int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve); + +/* Multiplies a point by a scalar. Points are represented by the X coordinate followed by + the Y coordinate in the same array, both coordinates are curve->num_words long. Note + that scalar must be curve->num_n_words long (NOT curve->num_words). */ +void uECC_point_mult(uECC_word_t *result, + const uECC_word_t *point, + const uECC_word_t *scalar, + uECC_Curve curve); + +/* Generates a random integer in the range 0 < random < top. + Both random and top have num_words words. */ +int uECC_generate_random_int(uECC_word_t *random, + const uECC_word_t *top, + wordcount_t num_words); + +#endif /* uECC_ENABLE_VLI_API */ + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _UECC_VLI_H_ */ diff --git a/core/embed/ble_firmware/version.h b/core/embed/ble_firmware/version.h new file mode 100644 index 000000000..14de53045 --- /dev/null +++ b/core/embed/ble_firmware/version.h @@ -0,0 +1,4 @@ +#define VERSION_MAJOR 0 +#define VERSION_MINOR 0 +#define VERSION_PATCH 0 +#define VERSION_BUILD 0 diff --git a/core/site_scons/tools.py b/core/site_scons/tools.py index 8c64bfdb2..cc5fddfd3 100644 --- a/core/site_scons/tools.py +++ b/core/site_scons/tools.py @@ -99,6 +99,25 @@ def get_version(file: str) -> str: return f"{major}.{minor}.{patch}" +def get_version_int(file): + major = 0 + minor = 0 + patch = 0 + + file = PROJECT_ROOT / file + with open(file, 'r') as f: + for line in f: + if line.startswith('#define VERSION_MAJOR '): + major = int(line.split('VERSION_MAJOR')[1].strip()) + if line.startswith('#define VERSION_MINOR '): + minor = int(line.split('VERSION_MINOR')[1].strip()) + if line.startswith('#define VERSION_PATCH '): + patch = int(line.split('VERSION_PATCH')[1].strip()) + if major > 99 or minor > 99 or patch > 99: + raise Exception("Version number too large") + return major * 10000 + minor * 100 + patch + + def get_git_revision_hash() -> str: return subprocess.check_output(["git", "rev-parse", "HEAD"]).decode("ascii").strip() diff --git a/core/tools/convert_ble_firmware.py b/core/tools/convert_ble_firmware.py new file mode 100644 index 000000000..c7509ce3a --- /dev/null +++ b/core/tools/convert_ble_firmware.py @@ -0,0 +1,35 @@ +import click +import zipfile + + +def convert_file(archive, infile, outfile, name): + data = archive.read(infile) + with open(outfile, "w") as outfile: + outfile.write("// Firmware BLOB - automatically generated\n") + outfile.write("\n") + outfile.write(f"#ifndef __FW_BLOB_{name}_H__\n") + outfile.write(f"#define __FW_BLOB_{name}_H__ 1\n") + outfile.write("\n") + + outfile.write(f"uint8_t {name}[] = " + "{") + + for i, byte in enumerate(data): + if i % 16 == 0: + outfile.write("\n ") + outfile.write("0x{:02x}, ".format(byte)) + + outfile.write("\n};\n") + outfile.write("\n") + outfile.write("#endif\n") + + +@click.command() +@click.argument("infile", type=click.File("rb")) +def convert(infile): + with zipfile.ZipFile(infile) as archive: + convert_file(archive, "ble_firmware.bin", "./embed/firmware/dfu/ble_firmware_bin.h", "binfile") + convert_file(archive, "ble_firmware.dat", "./embed/firmware/dfu/ble_firmware_dat.h", "datfile") + + +if __name__ == "__main__": + convert() diff --git a/core/tools/generate_ble_bl_settings.sh b/core/tools/generate_ble_bl_settings.sh new file mode 100644 index 000000000..e407e8475 --- /dev/null +++ b/core/tools/generate_ble_bl_settings.sh @@ -0,0 +1 @@ +nrfutil settings generate --family NRF52 --bootloader-version 0 --bl-settings-version 2 --app-boot-validation VALIDATE_ECDSA_P256_SHA256 --application ./build/ble_firmware/ble_firmware.hex --application-version 0 --sd-boot-validation VALIDATE_ECDSA_P256_SHA256 --softdevice ./embed/sdk/nrf52/components/softdevice/s140/hex/s140_nrf52_7.2.0_softdevice.hex --key-file ./embed/ble_bootloader/priv.pem ./build/ble_bootloader/settings.hex diff --git a/tools/style.c.exclude b/tools/style.c.exclude index e643d7575..1d04e7c0b 100644 --- a/tools/style.c.exclude +++ b/tools/style.c.exclude @@ -12,3 +12,6 @@ ^\./crypto/sha3 ^\./legacy/vendor ^\./core/embed/segger +^\./core/embed/ble_bootloader/dfu +^\./core/embed/ble_firmware/uecc +^\./core/embed/sdk