diff --git a/.github/workflows/scripts/linux/build-dependencies-qt.sh b/.github/workflows/scripts/linux/build-dependencies-qt.sh index dfdcbd75a1..5a502f648a 100755 --- a/.github/workflows/scripts/linux/build-dependencies-qt.sh +++ b/.github/workflows/scripts/linux/build-dependencies-qt.sh @@ -24,7 +24,7 @@ QTAPNG=1.3.0 FFMPEG=8.1 LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075 LIBJPEGTURBO=3.1.4.1 -LIBPNG=1.6.56 +LIBPNG=1.6.58 LIBWEBP=1.6.0 NVENC=13.0.19.0 SDL=SDL3-3.4.8 @@ -34,12 +34,12 @@ ZSTD=1.5.7 KDDOCKWIDGETS=2.4.0 PLUTOVG=1.3.2 PLUTOSVG=0.0.7 -RAPIDYAML=0.11.1 +RAPIDYAML=0.12.1 -SHADERC=2026.1 -SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951 -SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174 -SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093 +SHADERC=2026.2 +SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c +SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375 +SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73 mkdir -p deps-build cd deps-build @@ -58,10 +58,10 @@ f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz 96e5c2d7f2c482a60d5804da48a2eb9a0db0719b2c65dcc169fbfdcf37f3a45d libbacktrace-$LIBBACKTRACE.tar.gz ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz -f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz +28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz -9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz +eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz 13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz @@ -69,12 +69,12 @@ eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar 51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz 7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz 78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz -9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz +e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz -245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz -bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz -1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz -cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz +f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz +971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz +a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz +e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz EOF if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then diff --git a/.github/workflows/scripts/linux/build-dependencies-runner.sh b/.github/workflows/scripts/linux/build-dependencies-runner.sh index e2d90ebcf8..fb3d2cb7b1 100755 --- a/.github/workflows/scripts/linux/build-dependencies-runner.sh +++ b/.github/workflows/scripts/linux/build-dependencies-runner.sh @@ -24,7 +24,7 @@ LZ4=1.10.0 ZSTD=1.5.7 PLUTOVG=1.3.2 PLUTOSVG=0.0.7 -RAPIDYAML=0.11.1 +RAPIDYAML=0.12.1 SHADERC=2025.4 SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d @@ -50,7 +50,7 @@ c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv- 06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz 7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz 78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz -9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz +e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz EOF if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then diff --git a/.github/workflows/scripts/linux/flatpak/modules/22-shaderc.json b/.github/workflows/scripts/linux/flatpak/modules/22-shaderc.json index 4765896b60..e9f757d566 100644 --- a/.github/workflows/scripts/linux/flatpak/modules/22-shaderc.json +++ b/.github/workflows/scripts/linux/flatpak/modules/22-shaderc.json @@ -15,24 +15,24 @@ { "type": "git", "url": "https://github.com/google/shaderc.git", - "commit": "301b4ede53d59b68bf55f95bb26412d9233c8187" + "commit": "d5f08ae5c5a9a45165578445cbd0f9adf0223448" }, { "type": "archive", - "url": "https://github.com/KhronosGroup/glslang/archive/f0bd0257c308b9a26562c1a30c4748a0219cc951.tar.gz", - "sha256": "bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647", + "url": "https://github.com/KhronosGroup/glslang/archive/275822a6261ee689aadb1da5f09a0ec2f058685c.tar.gz", + "sha256": "971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a", "dest": "third_party/glslang" }, { "type": "archive", - "url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/04f10f650d514df88b76d25e83db360142c7b174.tar.gz", - "sha256": "1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded", + "url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/58006c901d1d5c37dece6b6610e9af87fa951375.tar.gz", + "sha256": "a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c", "dest": "third_party/spirv-headers" }, { "type": "archive", - "url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/fbe4f3ad913c44fe8700545f8ffe35d1382b7093.tar.gz", - "sha256": "cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59", + "url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/6337eb62cadd7d124ac6789bf39c0f71148f0a73.tar.gz", + "sha256": "e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2", "dest": "third_party/spirv-tools" }, { diff --git a/.github/workflows/scripts/linux/flatpak/modules/26-libpng.json b/.github/workflows/scripts/linux/flatpak/modules/26-libpng.json index a0c4e7417f..6d4e2fb2d3 100644 --- a/.github/workflows/scripts/linux/flatpak/modules/26-libpng.json +++ b/.github/workflows/scripts/linux/flatpak/modules/26-libpng.json @@ -14,21 +14,21 @@ "sources": [ { "type": "archive", - "url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.56/libpng-1.6.56.tar.xz", - "sha256": "f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18" + "url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.58/libpng-1.6.58.tar.xz", + "sha256": "28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775" }, { "type": "file", - "url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.56-apng.patch.gz", - "dest-filename": "libpng-1.6.56-apng.patch.gz", - "sha256": "9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8" + "url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.58-apng.patch.gz", + "dest-filename": "libpng-1.6.58-apng.patch.gz", + "sha256": "eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0" }, { "type": "shell", "commands": [ - "gunzip -f libpng-1.6.56-apng.patch.gz", - "patch -p1 < \"libpng-1.6.56-apng.patch\"" + "gunzip -f libpng-1.6.58-apng.patch.gz", + "patch -p1 < \"libpng-1.6.58-apng.patch\"" ] } ], diff --git a/.github/workflows/scripts/linux/flatpak/modules/28-rapidyaml.json b/.github/workflows/scripts/linux/flatpak/modules/28-rapidyaml.json index 2e24cdde6a..d41aa28938 100644 --- a/.github/workflows/scripts/linux/flatpak/modules/28-rapidyaml.json +++ b/.github/workflows/scripts/linux/flatpak/modules/28-rapidyaml.json @@ -12,8 +12,8 @@ { "type": "git", "url": "https://github.com/biojppm/rapidyaml.git", - "tag": "v0.11.1", - "commit": "119b6042064d3828819e428e32e5a0f3035d5643" + "tag": "v0.12.1", + "commit": "b56567b0bd24e9ce7beb08d6950a5732f62f6e74" } ], "cleanup": [ diff --git a/.github/workflows/scripts/macos/build-dependencies-universal.sh b/.github/workflows/scripts/macos/build-dependencies-universal.sh index 8efb099a01..93b7bc155f 100755 --- a/.github/workflows/scripts/macos/build-dependencies-universal.sh +++ b/.github/workflows/scripts/macos/build-dependencies-universal.sh @@ -48,10 +48,10 @@ QTAPNG=1.3.0 FREETYPE=2.14.3 SDL=SDL3-3.4.8 -HARFBUZZ=14.0.0 +HARFBUZZ=14.2.0 ZSTD=1.5.7 LZ4=1.10.0 -LIBPNG=1.6.56 +LIBPNG=1.6.58 LIBJPEGTURBO=3.1.4.1 LIBWEBP=1.6.0 FFMPEG=8.1 @@ -59,12 +59,12 @@ MOLTENVK=1.4.1 KDDOCKWIDGETS=2.4.0 PLUTOVG=1.3.2 PLUTOSVG=0.0.7 -RAPIDYAML=0.11.1 +RAPIDYAML=0.12.1 -SHADERC=2026.1 -SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951 -SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174 -SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093 +SHADERC=2026.2 +SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c +SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375 +SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73 mkdir -p deps-build cd deps-build @@ -94,24 +94,24 @@ f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG 36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz -f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz +c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz -f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz +28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz -9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz +eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz 9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz 51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz 7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz 78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz -9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz +e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz -245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz -bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz -1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz -cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz +f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz +971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz +a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz +e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz EOF if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then diff --git a/.github/workflows/scripts/macos/build-dependencies.sh b/.github/workflows/scripts/macos/build-dependencies.sh index 52503be7ce..cd66048ac0 100755 --- a/.github/workflows/scripts/macos/build-dependencies.sh +++ b/.github/workflows/scripts/macos/build-dependencies.sh @@ -25,10 +25,10 @@ QTAPNG=1.3.0 FREETYPE=2.14.3 SDL=SDL3-3.4.8 -HARFBUZZ=14.0.0 +HARFBUZZ=14.2.0 ZSTD=1.5.7 LZ4=1.10.0 -LIBPNG=1.6.56 +LIBPNG=1.6.58 LIBJPEGTURBO=3.1.4.1 LIBWEBP=1.6.0 FFMPEG=8.1 @@ -36,12 +36,12 @@ MOLTENVK=1.4.1 KDDOCKWIDGETS=2.4.0 PLUTOVG=1.3.2 PLUTOSVG=0.0.7 -RAPIDYAML=0.11.1 +RAPIDYAML=0.12.1 -SHADERC=2026.1 -SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951 -SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174 -SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093 +SHADERC=2026.2 +SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c +SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375 +SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73 mkdir -p deps-build cd deps-build @@ -70,24 +70,24 @@ f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG 36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz -f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz +c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz 537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz -f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz +28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz -9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz +eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz 9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz 51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz 7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz 78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz -9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz +e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz -245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz -bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz -1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz -cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz +f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz +971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz +a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz +e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz EOF if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then diff --git a/.github/workflows/scripts/windows/build-dependencies-arm64.bat b/.github/workflows/scripts/windows/build-dependencies-arm64.bat index e060115b69..0458903f2a 100644 --- a/.github/workflows/scripts/windows/build-dependencies-arm64.bat +++ b/.github/workflows/scripts/windows/build-dependencies-arm64.bat @@ -59,11 +59,11 @@ set QTMINOR=6.11 set QTAPNG=1.3.0 set FREETYPE=2.14.3 -set HARFBUZZ=14.0.0 +set HARFBUZZ=14.2.0 set SDL=SDL3-3.4.8 set LIBJPEGTURBO=3.1.4.1 -set LIBPNG=1656 -set LIBPNGLONG=1.6.56 +set LIBPNG=1658 +set LIBPNGLONG=1.6.58 set LZ4=1.10.0 set WEBP=1.6.0 set ZLIB=1.3.2 @@ -72,14 +72,14 @@ set ZSTD=1.5.7 set KDDOCKWIDGETS=2.4.0 set PLUTOVG=1.3.2 set PLUTOSVG=0.0.7 -set RAPIDYAML=0.11.1 +set RAPIDYAML=0.12.1 -set SHADERC=2026.1 -set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951 -set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174 -set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093 +set SHADERC=2026.2 +set SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c +set SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375 +set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73 -set AGILITYSDK=1.619.1 +set AGILITYSDK=1.619.2 call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error @@ -89,9 +89,9 @@ call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error -call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error -call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error -call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error +call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error +call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error +call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error @@ -101,13 +101,13 @@ call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/r call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error -call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error -call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error +call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" eb92d90bb23b2ec23410c41d791e41dbdbec942ab946924d1fdcb31eac6f0735 || goto error +call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 96276f55b9fa7837ac8f3f72fd52965879cbb5d5d2e6af548c69a177fb078304 || goto error -call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error -call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error -call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error -call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error +call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" f9401cc5cb36c276cd1e072b6595dbd728148e8dba389e50f7339e2d388dbc08 || goto error +call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 2b63189efad0348d88d410a5e12ec550a612e0b6ceef64624b8f45491269fb9c || goto error +call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" d2f071e94c081f5a4606559770ebf1f7d1eac92a1def0c3e10609844aa8b69b2 || goto error +call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 4011be89aa73e3461c9deef73936a62c79a3097590c5135d058041cc9fb99c6f || goto error if %DEBUG%==1 ( echo Building debug and release libraries... diff --git a/.github/workflows/scripts/windows/build-dependencies.bat b/.github/workflows/scripts/windows/build-dependencies.bat index b78437756e..9e1f413bf6 100644 --- a/.github/workflows/scripts/windows/build-dependencies.bat +++ b/.github/workflows/scripts/windows/build-dependencies.bat @@ -76,11 +76,11 @@ set LIBSVTAV1=4.0.1 set LIBX264=b35605ace3ddf7c1a5d67a2eb553f034aef41d55 set FREETYPE=2.14.3 -set HARFBUZZ=14.0.0 +set HARFBUZZ=14.2.0 set SDL=SDL3-3.4.8 set LIBJPEGTURBO=3.1.4.1 -set LIBPNG=1656 -set LIBPNGLONG=1.6.56 +set LIBPNG=1658 +set LIBPNGLONG=1.6.58 set LZ4=1.10.0 set WEBP=1.6.0 set ZLIB=1.3.2 @@ -89,14 +89,14 @@ set ZSTD=1.5.7 set KDDOCKWIDGETS=2.4.0 set PLUTOVG=1.3.2 set PLUTOSVG=0.0.7 -set RAPIDYAML=0.11.1 +set RAPIDYAML=0.12.1 -set SHADERC=2026.1 -set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951 -set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174 -set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093 +set SHADERC=2026.2 +set SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c +set SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375 +set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73 -set AGILITYSDK=1.619.1 +set AGILITYSDK=1.619.2 call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error @@ -116,9 +116,9 @@ call :downloadfile "SVT-AV1-v%LIBSVTAV1%.zip" "https://gitlab.com/AOMediaCodec/S call :downloadfile "x264-%LIBX264%.zip" "https://code.videolan.org/videolan/x264/-/archive/%LIBX264%.zip" d95d059eff81cc565165cd058b66e208f0cc9874106a8fe94a811a66cf8a85a2 || goto error call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error -call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error -call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error -call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error +call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error +call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error +call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error @@ -128,13 +128,13 @@ call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/r call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error -call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error -call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error +call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" eb92d90bb23b2ec23410c41d791e41dbdbec942ab946924d1fdcb31eac6f0735 || goto error +call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 96276f55b9fa7837ac8f3f72fd52965879cbb5d5d2e6af548c69a177fb078304 || goto error -call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error -call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error -call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error -call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error +call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" f9401cc5cb36c276cd1e072b6595dbd728148e8dba389e50f7339e2d388dbc08 || goto error +call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 2b63189efad0348d88d410a5e12ec550a612e0b6ceef64624b8f45491269fb9c || goto error +call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" d2f071e94c081f5a4606559770ebf1f7d1eac92a1def0c3e10609844aa8b69b2 || goto error +call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 4011be89aa73e3461c9deef73936a62c79a3097590c5135d058041cc9fb99c6f || goto error if %DEBUG%==1 ( echo Building debug and release libraries... diff --git a/3rdparty/cpuinfo/.gitignore b/3rdparty/cpuinfo/.gitignore index f069f195f7..8a4664124f 100644 --- a/3rdparty/cpuinfo/.gitignore +++ b/3rdparty/cpuinfo/.gitignore @@ -11,6 +11,10 @@ obj/ *.pyc *.pyo +# Bazel-related files +bazel-* +MODULE.bazel.lock + # System files .DS_Store .DS_Store? diff --git a/3rdparty/cpuinfo/CMakeLists.txt b/3rdparty/cpuinfo/CMakeLists.txt index 0542f3140f..6bb4687cde 100644 --- a/3rdparty/cpuinfo/CMakeLists.txt +++ b/3rdparty/cpuinfo/CMakeLists.txt @@ -42,7 +42,7 @@ ENDMACRO() MACRO(CPUINFO_TARGET_ENABLE_CXX11 target) SET_TARGET_PROPERTIES(${target} PROPERTIES - CXX_STANDARD 14 + CXX_STANDARD 17 CXX_EXTENSIONS NO) ENDMACRO() diff --git a/3rdparty/cpuinfo/cmake/DownloadGoogleTest.cmake b/3rdparty/cpuinfo/cmake/DownloadGoogleTest.cmake index d69d19a3a8..22f7fe4023 100644 --- a/3rdparty/cpuinfo/cmake/DownloadGoogleTest.cmake +++ b/3rdparty/cpuinfo/cmake/DownloadGoogleTest.cmake @@ -1,11 +1,11 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR) +CMAKE_MINIMUM_REQUIRED(VERSION 3.18 FATAL_ERROR) PROJECT(googletest-download NONE) INCLUDE(ExternalProject) ExternalProject_Add(googletest - URL https://github.com/google/googletest/archive/release-1.8.0.zip - URL_HASH SHA256=f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf + URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip + URL_HASH SHA256=40d4ec942217dcc84a9ebe2a68584ada7d4a33a8ee958755763278ea1c5e18ff SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/googletest" BINARY_DIR "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest" CONFIGURE_COMMAND "" diff --git a/3rdparty/cpuinfo/deps/clog/CMakeLists.txt b/3rdparty/cpuinfo/deps/clog/CMakeLists.txt index 6e50c41c38..f40319a2ab 100644 --- a/3rdparty/cpuinfo/deps/clog/CMakeLists.txt +++ b/3rdparty/cpuinfo/deps/clog/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR) +CMAKE_MINIMUM_REQUIRED(VERSION 3.10 FATAL_ERROR) INCLUDE(GNUInstallDirs) diff --git a/3rdparty/cpuinfo/include/cpuinfo.h b/3rdparty/cpuinfo/include/cpuinfo.h index 82c20f1cbb..381018da65 100644 --- a/3rdparty/cpuinfo/include/cpuinfo.h +++ b/3rdparty/cpuinfo/include/cpuinfo.h @@ -355,6 +355,12 @@ enum cpuinfo_uarch { cpuinfo_uarch_sunny_cove = 0x0010020C, /** Intel Willow Cove microarchitecture (10 nm, Tiger Lake). */ cpuinfo_uarch_willow_cove = 0x0010020D, + /** Intel Golden Cove microarchitecture (Sapphire Rapids). */ + cpuinfo_uarch_golden_cove = 0x0010020E, + /** Intel Raptor Cove microarchitecture (Emerald Rapids). */ + cpuinfo_uarch_raptor_cove = 0x0010020F, + /** Intel Redwood Cove microarchitecture (Granite Rapids). */ + cpuinfo_uarch_redwood_cove = 0x00100210, /** Pentium 4 with Willamette, Northwood, or Foster cores. */ cpuinfo_uarch_willamette = 0x00100300, @@ -519,6 +525,8 @@ enum cpuinfo_uarch { cpuinfo_uarch_cortex_a510 = 0x00300551, /** ARM Cortex-A520. */ cpuinfo_uarch_cortex_a520 = 0x00300552, + /** ARM Cortex-A320. */ + cpuinfo_uarch_cortex_a320 = 0x00300553, /** ARM Cortex-A710. */ cpuinfo_uarch_cortex_a710 = 0x00300571, /** ARM Cortex-A715. */ @@ -2226,6 +2234,12 @@ struct cpuinfo_riscv_isa { bool c; /* Vector Extension. */ bool v; + + /* ISA Extensions */ + /* Half-Precision Floating-Point Extension. */ + bool zfh; + /* Half-Precision Floating-Point Vector Extension. */ + bool zvfh; }; extern struct cpuinfo_riscv_isa cpuinfo_isa; @@ -2301,6 +2315,22 @@ static inline bool cpuinfo_has_riscv_v(void) { #endif } +static inline bool cpuinfo_has_riscv_zfh(void) { +#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 + return cpuinfo_isa.zfh; +#else + return false; +#endif +} + +static inline bool cpuinfo_has_riscv_zvfh(void) { +#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64 + return cpuinfo_isa.zvfh; +#else + return false; +#endif +} + const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void); const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void); const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void); diff --git a/3rdparty/cpuinfo/src/arm/android/api.h b/3rdparty/cpuinfo/src/arm/android/api.h index 48ef14279e..51cc82209b 100644 --- a/3rdparty/cpuinfo/src/arm/android/api.h +++ b/3rdparty/cpuinfo/src/arm/android/api.h @@ -13,6 +13,7 @@ enum cpuinfo_android_chipset_property { cpuinfo_android_chipset_property_ro_arch, cpuinfo_android_chipset_property_ro_chipname, cpuinfo_android_chipset_property_ro_hardware_chipname, + cpuinfo_android_chipset_property_ro_soc_model, cpuinfo_android_chipset_property_max, }; diff --git a/3rdparty/cpuinfo/src/arm/android/properties.c b/3rdparty/cpuinfo/src/arm/android/properties.c index 51a2def952..2da3fd0f00 100644 --- a/3rdparty/cpuinfo/src/arm/android/properties.c +++ b/3rdparty/cpuinfo/src/arm/android/properties.c @@ -63,4 +63,7 @@ void cpuinfo_arm_android_parse_properties(struct cpuinfo_android_properties prop cpuinfo_android_property_get("ro.hardware.chipname", properties->ro_hardware_chipname); cpuinfo_log_debug( "read ro.hardware.chipname = \"%.*s\"", ro_hardware_chipname_length, properties->ro_hardware_chipname); + + const int ro_soc_model_length = cpuinfo_android_property_get("ro.soc.model", properties->ro_soc_model); + cpuinfo_log_debug("read ro.soc.model = \"%.*s\"", ro_soc_model_length, properties->ro_soc_model); } diff --git a/3rdparty/cpuinfo/src/arm/api.h b/3rdparty/cpuinfo/src/arm/api.h index 32a271c4ce..cfb99ff40f 100644 --- a/3rdparty/cpuinfo/src/arm/api.h +++ b/3rdparty/cpuinfo/src/arm/api.h @@ -45,6 +45,7 @@ enum cpuinfo_arm_chipset_series { cpuinfo_arm_chipset_series_qualcomm_msm, cpuinfo_arm_chipset_series_qualcomm_apq, cpuinfo_arm_chipset_series_qualcomm_snapdragon, + cpuinfo_arm_chipset_series_qualcomm_sm, cpuinfo_arm_chipset_series_mediatek_mt, cpuinfo_arm_chipset_series_samsung_exynos, cpuinfo_arm_chipset_series_hisilicon_k3v, diff --git a/3rdparty/cpuinfo/src/arm/linux/api.h b/3rdparty/cpuinfo/src/arm/linux/api.h index 14fed7ceb5..453b1e9006 100644 --- a/3rdparty/cpuinfo/src/arm/linux/api.h +++ b/3rdparty/cpuinfo/src/arm/linux/api.h @@ -29,6 +29,7 @@ struct cpuinfo_android_properties { char ro_arch[CPUINFO_BUILD_PROP_VALUE_MAX]; char ro_chipname[CPUINFO_BUILD_PROP_VALUE_MAX]; char ro_hardware_chipname[CPUINFO_BUILD_PROP_VALUE_MAX]; + char ro_soc_model[CPUINFO_BUILD_PROP_VALUE_MAX]; }; #endif @@ -364,6 +365,8 @@ CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_f const char ro_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]); CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname( const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]); +CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model( + const char ro_soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]); #else CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision( const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]); diff --git a/3rdparty/cpuinfo/src/arm/linux/chipset.c b/3rdparty/cpuinfo/src/arm/linux/chipset.c index 93de535fe4..0a0364249a 100644 --- a/3rdparty/cpuinfo/src/arm/linux/chipset.c +++ b/3rdparty/cpuinfo/src/arm/linux/chipset.c @@ -264,7 +264,7 @@ static bool match_sm(const char* start, const char* end, struct cpuinfo_arm_chip /* Return parsed chipset. */ *chipset = (struct cpuinfo_arm_chipset){ .vendor = cpuinfo_arm_chipset_vendor_qualcomm, - .series = cpuinfo_arm_chipset_series_qualcomm_snapdragon, + .series = cpuinfo_arm_chipset_series_qualcomm_sm, .model = model, }; return true; @@ -3491,6 +3491,36 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_chipname( .series = cpuinfo_arm_chipset_series_unknown, }; } + +struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model( + const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]) { + struct cpuinfo_arm_chipset chipset; + const size_t soc_model_length = strnlen(soc_model, CPUINFO_BUILD_PROP_VALUE_MAX); + const char* soc_model_end = soc_model + soc_model_length; + + /* Check Qualcomm SMxxxx signature */ + if (match_sm(soc_model, soc_model_end, &chipset)) { + cpuinfo_log_debug( + "matched Qualcomm SM signature in ro.soc.model string \"%.*s\"", + (int)soc_model_length, + soc_model); + return chipset; + } + + /* Check Qualcomm MSM/APQ signatures */ + if (match_msm_apq(soc_model, soc_model_end, &chipset)) { + cpuinfo_log_debug( + "matched Qualcomm MSM/APQ signature in ro.soc.model string \"%.*s\"", + (int)soc_model_length, + soc_model); + return chipset; + } + + return (struct cpuinfo_arm_chipset){ + .vendor = cpuinfo_arm_chipset_vendor_unknown, + .series = cpuinfo_arm_chipset_series_unknown, + }; +} #endif /* __ANDROID__ */ /* @@ -3837,6 +3867,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = { [cpuinfo_arm_chipset_series_qualcomm_msm] = "MSM", [cpuinfo_arm_chipset_series_qualcomm_apq] = "APQ", [cpuinfo_arm_chipset_series_qualcomm_snapdragon] = "Snapdragon ", + [cpuinfo_arm_chipset_series_qualcomm_sm] = "SM", [cpuinfo_arm_chipset_series_mediatek_mt] = "MT", [cpuinfo_arm_chipset_series_samsung_exynos] = "Exynos ", [cpuinfo_arm_chipset_series_hisilicon_k3v] = "K3V", @@ -4074,6 +4105,8 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset( cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_chipname), [cpuinfo_android_chipset_property_ro_hardware_chipname] = cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_hardware_chipname), + [cpuinfo_android_chipset_property_ro_soc_model] = + cpuinfo_arm_android_decode_chipset_from_ro_soc_model(properties->ro_soc_model), }; enum cpuinfo_arm_chipset_vendor vendor = cpuinfo_arm_chipset_vendor_unknown; for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) { diff --git a/3rdparty/cpuinfo/src/arm/linux/init.c b/3rdparty/cpuinfo/src/arm/linux/init.c index 1eab69d5fc..1bf0014de6 100644 --- a/3rdparty/cpuinfo/src/arm/linux/init.c +++ b/3rdparty/cpuinfo/src/arm/linux/init.c @@ -1,5 +1,7 @@ +#include #include #include +#include #include #include @@ -14,6 +16,92 @@ #include #include +/* Parse a uint32 from sysfs file content */ +static bool uint32_parser(const char* filename, const char* text_start, const char* text_end, void* context) { + uint32_t* value_ptr = (uint32_t*)context; + if (text_start == text_end) { + return false; + } + uint32_t value = 0; + for (const char* p = text_start; p < text_end && *p >= '0' && *p <= '9'; p++) { + value = value * 10 + (*p - '0'); + } + *value_ptr = value; + return value > 0; +} + +/* Parse cache size with K/M suffix from /sys/devices/system/cpu/cpuN/cache/indexN/size (e.g. "2048K", "1M") */ +static bool cache_size_parser(const char* filename, const char* text_start, const char* text_end, void* context) { + uint32_t* size_ptr = (uint32_t*)context; + if (text_start == text_end) { + return false; + } + uint32_t value = 0; + const char* p = text_start; + while (p < text_end && *p >= '0' && *p <= '9') { + value = value * 10 + (*p - '0'); + p++; + } + if (p == text_start || value == 0) { + return false; + } + uint32_t multiplier = 1024; + if (p < text_end && toupper(*p) == 'M') { + multiplier = 1024 * 1024; + } + *size_ptr = value * multiplier; + return true; +} + +/* Check if /sys/devices/system/cpu/cpuN/cache/index2/shared_cpu_list indicates a single CPU (per-core cache) */ +static bool shared_cpu_list_parser(const char* filename, const char* text_start, const char* text_end, void* context) { + bool* is_per_core = (bool*)context; + for (const char* p = text_start; p < text_end; p++) { + if (*p == ',' || *p == '-') { + *is_per_core = false; + return true; + } + } + *is_per_core = (text_start != text_end); + return *is_per_core; +} + +/* + * Read cache size from sysfs. + * + * ARM CPUs lack a CPUID-equivalent instruction to query cache properties, + * so the library relies on hardcoded values that are often incorrect. + * Linux exposes cache topology via sysfs (existed before 2008, documented 2014): + * https://raw.githubusercontent.com/torvalds/linux/master/Documentation/ABI/testing/sysfs-devices-system-cpu + * + */ +static uint32_t cpuinfo_linux_read_sysfs_cache_size(uint32_t cpu_id, uint32_t cache_level) { + char path[256]; + + /* Verify the index corresponds to the requested cache level */ + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index%u/level", cpu_id, cache_level); + uint32_t actual_level = 0; + if (!cpuinfo_linux_parse_small_file(path, 16, uint32_parser, &actual_level) || actual_level != cache_level) { + return 0; + } + + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index%u/size", cpu_id, cache_level); + uint32_t size = 0; + if (!cpuinfo_linux_parse_small_file(path, 32, cache_size_parser, &size)) { + return 0; + } + return size; +} + +/* Check if L2 cache is per-core by reading sysfs shared_cpu_list */ +static bool cpuinfo_linux_is_l2_per_core(uint32_t cpu_id) { + char path[256]; + snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index2/shared_cpu_list", cpu_id); + bool is_per_core = false; + cpuinfo_linux_parse_small_file(path, 128, shared_cpu_list_parser, &is_per_core); + return is_per_core; +} + struct cpuinfo_arm_isa cpuinfo_isa = {0}; static struct cpuinfo_package package = {{0}}; @@ -719,11 +807,21 @@ void cpuinfo_arm_linux_init(void) { */ shared_l3 = false; if (temp_l2.size != 0) { - /* Assume L2 is shared by cores in the same - * cluster */ - if (arm_linux_processors[i].package_leader_id == - arm_linux_processors[i].system_processor_id) { + /* Check if L2 is per-core using sysfs */ + uint32_t sysfs_l2_size = cpuinfo_linux_read_sysfs_cache_size( + arm_linux_processors[i].system_processor_id, 2); + bool l2_is_per_core = (sysfs_l2_size > 0) && + cpuinfo_linux_is_l2_per_core(arm_linux_processors[i].system_processor_id); + + if (l2_is_per_core) { + /* L2 is private to each core */ l2_count += 1; + } else { + /* Assume L2 is shared by cores in the same cluster */ + if (arm_linux_processors[i].package_leader_id == + arm_linux_processors[i].system_processor_id) { + l2_count += 1; + } } } } @@ -771,10 +869,27 @@ void cpuinfo_arm_linux_init(void) { &temp_l2, &temp_l3); - if (temp_l3.size != 0) { + /* Try to read L2 cache size from sysfs (more accurate) */ + uint32_t sysfs_l2_size = + cpuinfo_linux_read_sysfs_cache_size(arm_linux_processors[i].system_processor_id, 2); + if (sysfs_l2_size > 0) { + temp_l2.size = sysfs_l2_size; + /* Recalculate sets to maintain consistency: size = associativity * sets * partitions * + * line_size */ + if (temp_l2.associativity > 0 && temp_l2.line_size > 0 && temp_l2.partitions > 0) { + temp_l2.sets = sysfs_l2_size / + (temp_l2.associativity * temp_l2.partitions * temp_l2.line_size); + } + } + + /* Check if L2 is per-core by reading sysfs */ + bool l2_is_per_core = (sysfs_l2_size > 0) && + cpuinfo_linux_is_l2_per_core(arm_linux_processors[i].system_processor_id); + + if (temp_l3.size != 0 || l2_is_per_core) { /* * Assumptions: - * - L2 is private to each core + * - L2 is private to each core (either has L3, or sysfs confirms per-core L2) * - L3 is shared by cores in the same cluster * - If cores in different clusters report the same L3, * it is shared between all cores. diff --git a/3rdparty/cpuinfo/src/arm/uarch.c b/3rdparty/cpuinfo/src/arm/uarch.c index 6f92c7d2bb..aab1001042 100644 --- a/3rdparty/cpuinfo/src/arm/uarch.c +++ b/3rdparty/cpuinfo/src/arm/uarch.c @@ -141,17 +141,20 @@ void cpuinfo_arm_decode_vendor_uarch( case 0xD87: /* Cortex-A725 */ *uarch = cpuinfo_uarch_cortex_a725; break; - case 0xD8C: - *uarch = cpuinfo_uarch_lumex_c1_ultra; - break; - case 0xD90: - *uarch = cpuinfo_uarch_lumex_c1_premium; + case 0xD8A: + *uarch = cpuinfo_uarch_lumex_c1_nano; break; case 0xD8B: *uarch = cpuinfo_uarch_lumex_c1_pro; break; - case 0xD8A: - *uarch = cpuinfo_uarch_lumex_c1_nano; + case 0xD8C: + *uarch = cpuinfo_uarch_lumex_c1_ultra; + break; + case 0xD8F: /* Cortex-A320 */ + *uarch = cpuinfo_uarch_cortex_a320; + break; + case 0xD90: + *uarch = cpuinfo_uarch_lumex_c1_premium; break; default: switch (midr_get_part(midr) >> 8) { diff --git a/3rdparty/cpuinfo/src/riscv/linux/api.h b/3rdparty/cpuinfo/src/riscv/linux/api.h index 829de84b50..1c356bfd5b 100644 --- a/3rdparty/cpuinfo/src/riscv/linux/api.h +++ b/3rdparty/cpuinfo/src/riscv/linux/api.h @@ -61,11 +61,13 @@ CPUINFO_INTERNAL void cpuinfo_riscv_linux_decode_isa_from_hwcap(struct cpuinfo_r * @param[processor] - The Linux ID of the target processor. * @param[vendor] - Reference to the cpuinfo_vendor to populate. * @param[uarch] - Reference to the cpuinfo_uarch to populate. + * @param[isa] - Reference to the cpuinfo_riscv_isa to populate isa extensions. */ CPUINFO_INTERNAL void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( uint32_t processor, enum cpuinfo_vendor vendor[restrict static 1], - enum cpuinfo_uarch uarch[restrict static 1]); + enum cpuinfo_uarch uarch[restrict static 1], + struct cpuinfo_riscv_isa isa[restrict static 1]); /* Used to determine which uarch is associated with the current thread. */ extern CPUINFO_INTERNAL const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map; diff --git a/3rdparty/cpuinfo/src/riscv/linux/init.c b/3rdparty/cpuinfo/src/riscv/linux/init.c index 9ab3d6e60c..45168c7e66 100644 --- a/3rdparty/cpuinfo/src/riscv/linux/init.c +++ b/3rdparty/cpuinfo/src/riscv/linux/init.c @@ -6,7 +6,7 @@ #include /* ISA structure to hold supported extensions. */ -struct cpuinfo_riscv_isa cpuinfo_isa; +struct cpuinfo_riscv_isa cpuinfo_isa = {0}; /* Helper function to bitmask flags and ensure operator precedence. */ static inline bool bitmask_all(uint32_t flags, uint32_t mask) { @@ -320,7 +320,8 @@ void cpuinfo_riscv_linux_init(void) { cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( processor, &riscv_linux_processors[processor].core.vendor, - &riscv_linux_processors[processor].core.uarch); + &riscv_linux_processors[processor].core.uarch, + &cpuinfo_isa); /* Populate frequency information of this core. */ uint32_t frequency = cpuinfo_linux_get_processor_cur_frequency(processor); diff --git a/3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c b/3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c index 63a92e24f7..f67dc46bed 100644 --- a/3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c +++ b/3rdparty/cpuinfo/src/riscv/linux/riscv-hw.c @@ -53,6 +53,30 @@ struct riscv_hwprobe { #define RISCV_HWPROBE_EXT_ZBB (1 << 4) #define RISCV_HWPROBE_EXT_ZBS (1 << 5) #define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6) +#define RISCV_HWPROBE_EXT_ZBC (1 << 7) +#define RISCV_HWPROBE_EXT_ZBKB (1 << 8) +#define RISCV_HWPROBE_EXT_ZBKC (1 << 9) +#define RISCV_HWPROBE_EXT_ZBKX (1 << 10) +#define RISCV_HWPROBE_EXT_ZKND (1 << 11) +#define RISCV_HWPROBE_EXT_ZKNE (1 << 12) +#define RISCV_HWPROBE_EXT_ZKNH (1 << 13) +#define RISCV_HWPROBE_EXT_ZKSED (1 << 14) +#define RISCV_HWPROBE_EXT_ZKSH (1 << 15) +#define RISCV_HWPROBE_EXT_ZKT (1 << 16) +#define RISCV_HWPROBE_EXT_ZVBB (1 << 17) +#define RISCV_HWPROBE_EXT_ZVBC (1 << 18) +#define RISCV_HWPROBE_EXT_ZVKB (1 << 19) +#define RISCV_HWPROBE_EXT_ZVKG (1 << 20) +#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21) +#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22) +#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23) +#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24) +#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25) +#define RISCV_HWPROBE_EXT_ZVKT (1 << 26) +#define RISCV_HWPROBE_EXT_ZFH (1 << 27) +#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28) +#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29) +#define RISCV_HWPROBE_EXT_ZVFH (1 << 30) #define RISCV_HWPROBE_KEY_CPUPERF_0 5 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0) #define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0) @@ -72,7 +96,8 @@ struct riscv_hwprobe { void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( uint32_t processor, enum cpuinfo_vendor vendor[restrict static 1], - enum cpuinfo_uarch uarch[restrict static 1]) { + enum cpuinfo_uarch uarch[restrict static 1], + struct cpuinfo_riscv_isa isa[restrict static 1]) { struct riscv_hwprobe pairs[] = { { .key = RISCV_HWPROBE_KEY_MVENDORID, @@ -83,6 +108,9 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( { .key = RISCV_HWPROBE_KEY_MIMPID, }, + { + .key = RISCV_HWPROBE_KEY_IMA_EXT_0, + }, }; const size_t pairs_count = sizeof(pairs) / sizeof(struct riscv_hwprobe); @@ -128,6 +156,7 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( uint32_t vendor_id = 0; uint32_t arch_id = 0; uint32_t imp_id = 0; + uint64_t ima_ext_0 = 0; for (size_t pair = 0; pair < pairs_count; pair++) { switch (pairs[pair].key) { case RISCV_HWPROBE_KEY_MVENDORID: @@ -139,6 +168,9 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( case RISCV_HWPROBE_KEY_MIMPID: imp_id = pairs[pair].value; break; + case RISCV_HWPROBE_KEY_IMA_EXT_0: + ima_ext_0 = pairs[pair].value; + break; default: /* The key value may be -1 if unsupported. */ break; @@ -146,6 +178,16 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe( } cpuinfo_riscv_decode_vendor_uarch(vendor_id, arch_id, imp_id, vendor, uarch); + /* Parse ISA extensions retrieved. */ + if (ima_ext_0 != 0) { + if (ima_ext_0 & RISCV_HWPROBE_EXT_ZFH) { + isa->zfh = true; + } + if (ima_ext_0 & RISCV_HWPROBE_EXT_ZVFH) { + isa->zvfh = true; + } + } + cleanup: CPU_FREE(cpu_set); } diff --git a/3rdparty/cpuinfo/src/x86/uarch.c b/3rdparty/cpuinfo/src/x86/uarch.c index 6e38aa8faf..4c0bafd0fe 100644 --- a/3rdparty/cpuinfo/src/x86/uarch.c +++ b/3rdparty/cpuinfo/src/x86/uarch.c @@ -171,6 +171,12 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch( case 0x8C: // Tiger U case 0x8D: // Tiger H return cpuinfo_uarch_willow_cove; + case 0x8F: // Sapphire Rapids + return cpuinfo_uarch_golden_cove; + case 0xCF: // Emerald Rapids + return cpuinfo_uarch_raptor_cove; + case 0xAD: // Granite Rapids + return cpuinfo_uarch_redwood_cove; /* Low-power cores */ case 0x1C: // Diamondville, // Silverthorne, diff --git a/3rdparty/cubeb/include/cubeb/cubeb.h b/3rdparty/cubeb/include/cubeb/cubeb.h index 2941b4baa8..ff2f8b7b98 100644 --- a/3rdparty/cubeb/include/cubeb/cubeb.h +++ b/3rdparty/cubeb/include/cubeb/cubeb.h @@ -585,8 +585,9 @@ cubeb_destroy(cubeb * context); NULL if this stream is input only. When input and output stream parameters are supplied, their rate has to be the same. - @param latency_frames Stream latency in frames. Valid range - is [1, 96000]. + @param latency_frames Requested stream latency in frames. Valid range is + [1, 96000]. The actual latency may differ depending + on the backend, platform, and hardware. @param data_callback Will be called to preroll data before playback is started by cubeb_stream_start. @param state_callback A pointer to a state callback. diff --git a/3rdparty/cubeb/src/cubeb_alsa.c b/3rdparty/cubeb/src/cubeb_alsa.c index f114f27d7b..be9faa490c 100644 --- a/3rdparty/cubeb/src/cubeb_alsa.c +++ b/3rdparty/cubeb/src/cubeb_alsa.c @@ -294,6 +294,9 @@ set_timeout(struct timeval * timeout, unsigned int ms) static void stream_buffer_decrement(cubeb_stream * stm, long count) { + if (count < 0 || (snd_pcm_uframes_t)count > stm->bufframes) { + count = stm->bufframes; + } char * bufremains = stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count); memmove(stm->buffer, bufremains, diff --git a/3rdparty/cubeb/src/cubeb_jack.cpp b/3rdparty/cubeb/src/cubeb_jack.cpp index b417078fc3..9d64b52c7a 100644 --- a/3rdparty/cubeb/src/cubeb_jack.cpp +++ b/3rdparty/cubeb/src/cubeb_jack.cpp @@ -405,12 +405,15 @@ cbjack_process(jack_nframes_t nframes, void * arg) for (int j = 0; j < MAX_STREAMS; j++) { cubeb_stream * stm = &ctx->streams[j]; - float * bufs_out[stm->out_params.channels]; - float * bufs_in[stm->in_params.channels]; if (!stm->in_use) continue; + float * bufs_out[MAX_CHANNELS] = {}; + float * bufs_in[MAX_CHANNELS] = {}; + XASSERT(stm->out_params.channels <= MAX_CHANNELS); + XASSERT(stm->in_params.channels <= MAX_CHANNELS); + // handle xruns by skipping audio that should have been played stm->position += t_jack_xruns * ctx->fragment_size * stm->ratio; @@ -851,6 +854,14 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream, return CUBEB_ERROR_INVALID_FORMAT; } + if ((output_stream_params && + (output_stream_params->channels < 1 || + output_stream_params->channels > MAX_CHANNELS)) || + (input_stream_params && (input_stream_params->channels < 1 || + input_stream_params->channels > MAX_CHANNELS))) { + return CUBEB_ERROR_INVALID_FORMAT; + } + if ((input_device && input_device != JACK_DEFAULT_IN) || (output_device && output_device != JACK_DEFAULT_OUT)) { return CUBEB_ERROR_NOT_SUPPORTED; diff --git a/3rdparty/cubeb/src/cubeb_wasapi.cpp b/3rdparty/cubeb/src/cubeb_wasapi.cpp index 36bad4bfac..592dab65e3 100644 --- a/3rdparty/cubeb/src/cubeb_wasapi.cpp +++ b/3rdparty/cubeb/src/cubeb_wasapi.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,7 @@ struct cubeb { }; class wasapi_endpoint_notification_client; +class wasapi_session_notification_client; /* We have three possible callbacks we can use with a stream: * - input only @@ -415,6 +417,10 @@ struct cubeb_stream { audio device changes and route the audio to the new default audio output device */ com_ptr notification_client; + /* Session notification client, to be notified when the audio session is + disconnected (e.g. when an audio device is removed from the system). */ + com_ptr session_control; + com_ptr session_notification_client; /* Main andle to the WASAPI capture stream. */ com_ptr input_client; /* Interface to use the event driven capture interface */ @@ -431,6 +437,10 @@ struct cubeb_stream { * practice, we read from the input stream in the output callback, so * this is not used, but it is necessary to start getting input data. */ HANDLE input_available_event = 0; + /* Signaled by stream_start/stream_stop when the active state changes, + so the render thread can promote/demote its MMCSS task accordingly + instead of remaining promoted while idle. */ + HANDLE mmcss_event = 0; /* Each cubeb_stream has its own thread. */ HANDLE thread = 0; /* The lock protects all members that are touched by the render thread or @@ -834,6 +844,89 @@ private: DWORD last_device_change; }; +class wasapi_session_notification_client : public IAudioSessionEvents { +public: + ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&ref_count); } + + ULONG STDMETHODCALLTYPE Release() + { + ULONG ulRef = InterlockedDecrement(&ref_count); + if (0 == ulRef) { + delete this; + } + return ulRef; + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID ** ppvInterface) + { + if (__uuidof(IUnknown) == riid) { + AddRef(); + *ppvInterface = (IUnknown *)this; + } else if (__uuidof(IAudioSessionEvents) == riid) { + AddRef(); + *ppvInterface = (IAudioSessionEvents *)this; + } else { + *ppvInterface = NULL; + return E_NOINTERFACE; + } + return S_OK; + } + + wasapi_session_notification_client(HANDLE event) + : ref_count(1), reconfigure_event(event) + { + } + + virtual ~wasapi_session_notification_client() {} + + HRESULT STDMETHODCALLTYPE + OnSessionDisconnected(AudioSessionDisconnectReason reason) + { + LOG("session: Audio session disconnected, reason: %d", reason); + BOOL ok = SetEvent(reconfigure_event); + if (!ok) { + LOG("session: SetEvent on reconfigure_event failed: %lx", GetLastError()); + } + return S_OK; + } + + HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(LPCWSTR value, + LPCGUID event_context) + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPCWSTR value, + LPCGUID event_context) + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(float volume, BOOL mute, + LPCGUID event_context) + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(DWORD channel_count, + float volumes[], + DWORD changed_channel, + LPCGUID event_context) + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(LPCGUID grouping_param, + LPCGUID event_context) + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE OnStateChanged(AudioSessionState state) + { + return S_OK; + } + +private: + LONG ref_count; + HANDLE reconfigure_event; +}; + namespace { long @@ -1414,8 +1507,9 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) } com; bool is_playing = true; - HANDLE wait_array[4] = {stm->shutdown_event, stm->reconfigure_event, - stm->refill_event, stm->input_available_event}; + HANDLE wait_array[5] = {stm->shutdown_event, stm->mmcss_event, + stm->reconfigure_event, stm->refill_event, + stm->input_available_event}; HANDLE mmcss_handle = NULL; HRESULT hr = 0; DWORD mmcss_task_index = 0; @@ -1428,15 +1522,6 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) return 0; } - /* We could consider using "Pro Audio" here for WebAudio and - maybe WebRTC. */ - mmcss_handle = AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index); - if (!mmcss_handle) { - /* This is not fatal, but we might glitch under heavy load. */ - LOG("Unable to use mmcss to bump the render thread priority: %lx", - GetLastError()); - } - while (is_playing) { DWORD waitResult = WaitForMultipleObjects(ARRAY_LENGTH(wait_array), wait_array, FALSE, INFINITE); @@ -1450,7 +1535,30 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) } continue; } - case WAIT_OBJECT_0 + 1: { /* reconfigure */ + case WAIT_OBJECT_0 + 1: { /* mmcss: active state changed */ + /* stm->active was set by wasapi_stream_start/_stop before signaling, + and SetEvent provides the necessary memory barrier. */ + if (stm->active && !mmcss_handle) { + /* We could consider using "Pro Audio" here for WebAudio and + maybe WebRTC. */ + mmcss_handle = + AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index); + if (!mmcss_handle) { + /* This is not fatal, but we might glitch under heavy load. */ + LOG("Unable to use mmcss to bump the render thread priority: %lx", + GetLastError()); + } else { + LOG("MMCSS render thread promoted (task index %lu)", + mmcss_task_index); + } + } else if (!stm->active && mmcss_handle) { + AvRevertMmThreadCharacteristics(mmcss_handle); + mmcss_handle = NULL; + LOG("MMCSS render thread demoted"); + } + continue; + } + case WAIT_OBJECT_0 + 2: { /* reconfigure */ auto_lock lock(stm->stream_reset_lock); if (!stm->active) { /* Avoid reconfiguring, stream start will handle it. */ @@ -1460,13 +1568,12 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) XASSERT(stm->output_client || stm->input_client); LOG("Reconfiguring the stream"); /* Close the stream */ - bool was_running = false; if (stm->output_client) { - was_running = stm->output_client->Stop() == S_OK; + stm->output_client->Stop(); LOG("Output stopped."); } if (stm->input_client) { - was_running = stm->input_client->Stop() == S_OK; + stm->input_client->Stop(); LOG("Input stopped."); } close_wasapi_stream(stm); @@ -1484,7 +1591,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) } LOG("Stream setup successfuly."); XASSERT(stm->output_client || stm->input_client); - if (was_running && stm->output_client) { + if (stm->output_client) { hr = stm->output_client->Start(); if (FAILED(hr)) { LOG("Error starting output after reconfigure, error: %lx", hr); @@ -1493,7 +1600,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) } LOG("Output started after reconfigure."); } - if (was_running && stm->input_client) { + if (stm->input_client) { hr = stm->input_client->Start(); if (FAILED(hr)) { LOG("Error starting input after reconfiguring, error: %lx", hr); @@ -1504,12 +1611,12 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream) } break; } - case WAIT_OBJECT_0 + 2: /* refill */ + case WAIT_OBJECT_0 + 3: /* refill */ XASSERT((has_input(stm) && has_output(stm)) || (!has_input(stm) && has_output(stm))); is_playing = stm->refill_callback(stm); break; - case WAIT_OBJECT_0 + 3: { /* input available */ + case WAIT_OBJECT_0 + 4: { /* input available */ bool rv = get_input_buffer(stm); if (!rv) { is_playing = false; @@ -2643,6 +2750,22 @@ setup_wasapi_stream(cubeb_stream * stm) return CUBEB_ERROR; } + hr = stm->output_client->GetService(__uuidof(IAudioSessionControl), + stm->session_control.receive_vpp()); + if (SUCCEEDED(hr)) { + stm->session_notification_client.reset( + new wasapi_session_notification_client(stm->reconfigure_event)); + hr = stm->session_control->RegisterAudioSessionNotification( + stm->session_notification_client.get()); + if (FAILED(hr)) { + LOG("Could not register session notification client: %lx", hr); + stm->session_notification_client = nullptr; + stm->session_control = nullptr; + } + } else { + LOG("Could not get the IAudioSessionControl: %lx", hr); + } + #ifdef CUBEB_WASAPI_USE_IAUDIOSTREAMVOLUME /* Restore the stream volume over a device change. */ if (stream_set_volume(stm, stm->volume) != CUBEB_OK) { @@ -2842,6 +2965,12 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream, return CUBEB_ERROR; } + stm->mmcss_event = CreateEvent(NULL, 0, 0, NULL); + if (!stm->mmcss_event) { + LOG("Can't create the mmcss event, error: %lx", GetLastError()); + return CUBEB_ERROR; + } + stm->thread_ready_event = CreateEvent(NULL, 0, 0, NULL); if (!stm->thread_ready_event) { LOG("Can't create the thread ready event, error: %lx", GetLastError()); @@ -2906,6 +3035,13 @@ close_wasapi_stream(cubeb_stream * stm) stm->stream_reset_lock.assert_current_thread_owns(); + if (stm->session_control && stm->session_notification_client) { + stm->session_control->UnregisterAudioSessionNotification( + stm->session_notification_client.get()); + stm->session_notification_client = nullptr; + stm->session_control = nullptr; + } + #ifdef CUBEB_WASAPI_USE_IAUDIOSTREAMVOLUME stm->audio_stream_volume = nullptr; #endif @@ -2960,6 +3096,7 @@ wasapi_stream_release(cubeb_stream * stm) CloseHandle(stm->reconfigure_event); CloseHandle(stm->refill_event); CloseHandle(stm->input_available_event); + CloseHandle(stm->mmcss_event); CloseHandle(stm->thread); @@ -3056,6 +3193,11 @@ wasapi_stream_start(cubeb_stream * stm) stm->active = true; + if (!SetEvent(stm->mmcss_event)) { + LOG("wasapi_stream_start: SetEvent(mmcss_event) failed: %lx", + GetLastError()); + } + stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED); return CUBEB_OK; @@ -3088,6 +3230,11 @@ wasapi_stream_stop(cubeb_stream * stm) stm->active = false; + if (!SetEvent(stm->mmcss_event)) { + LOG("wasapi_stream_stop: SetEvent(mmcss_event) failed: %lx", + GetLastError()); + } + wasapi_state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED); } @@ -3563,11 +3710,13 @@ wasapi_register_device_collection_changed( } if (collection_changed_callback) { - // Make sure it has been unregistered first. - XASSERT(((devtype & CUBEB_DEVICE_TYPE_INPUT) && - !context->input_collection_changed_callback) || - ((devtype & CUBEB_DEVICE_TYPE_OUTPUT) && - !context->output_collection_changed_callback)); + if (((devtype & CUBEB_DEVICE_TYPE_INPUT) && + context->input_collection_changed_callback) || + ((devtype & CUBEB_DEVICE_TYPE_OUTPUT) && + context->output_collection_changed_callback)) { + LOG("register_device_collection_changed: callback already registered"); + return CUBEB_ERROR_INVALID_PARAMETER; + } // Stop the notification client. Notifications arrive on // a separate thread. We stop them here to avoid diff --git a/3rdparty/fast_float/README.md b/3rdparty/fast_float/README.md index 8fdddbc5bf..be0f1f56c5 100644 --- a/3rdparty/fast_float/README.md +++ b/3rdparty/fast_float/README.md @@ -3,6 +3,9 @@ [![Ubuntu 22.04 CI (GCC 11)](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml/badge.svg)](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml) +*Note: This library is for C++ users. C programmers should consider [ffc.h](https://github.com/kolemannix/ffc.h). It is a high-performance port of fast_float to C.* + + The fast_float library provides fast header-only implementations for the C++ from_chars functions for `float` and `double` types as well as integer types. These functions convert ASCII strings representing decimal values (e.g., @@ -10,6 +13,7 @@ These functions convert ASCII strings representing decimal values (e.g., even). In our experience, these `fast_float` functions many times faster than comparable number-parsing functions from existing C++ standard libraries. + Specifically, `fast_float` provides the following two functions to parse floating-point numbers with a C++17-like syntax (the library itself only requires C++11): @@ -18,9 +22,9 @@ requires C++11): from_chars_result from_chars(char const *first, char const *last, float &value, ...); from_chars_result from_chars(char const *first, char const *last, double &value, ...); ``` +If they are available on your system, we also support fixed-width floating-point types such as `std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`. -You can also parse integer types: - +You can also parse integer types such as `char`, `short`, `long`, `long long`, `unsigned char`, `unsigned short`, `unsigned long`, `unsigned long long`, `bool` (0/1), `int8_t`, `int16_t`, `int32_t`, `int64_t`, `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`. ```C++ from_chars_result from_chars(char const *first, char const *last, int &value, ...); from_chars_result from_chars(char const *first, char const *last, unsigned &value, ...); @@ -69,7 +73,7 @@ int main() { } ``` -Though the C++17 standard has you do a comparison with `std::errc()` to check whether the conversion worked, you can avoid it by casting the result to a `bool` like so: +Prior to C++26, checking for a successful `std::from_chars` conversion requires comparing the `from_chars_result::ec` member to `std::errc()`. As an extension `fast_float::from_chars` supports the improved C++26 API that allows checking the result by converting it to `bool`, like so: ```cpp #include "fast_float/fast_float.h" @@ -83,7 +87,7 @@ int main() { std::cout << "parsed the number " << result << std::endl; return EXIT_SUCCESS; } - std::cerr << "failed to parse " << result << std::endl; + std::cerr << "failed to parse " << input << std::endl; return EXIT_FAILURE; } ``` @@ -141,9 +145,12 @@ Furthermore, we have the following restrictions: fixed-width floating-point types such as `std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`. * We only support the decimal format: we do not support hexadecimal strings. -* For values that are either very large or very small (e.g., `1e9999`), we - represent it using the infinity or negative infinity value and the returned +* For values that are very large positives or negatives (e.g., `1e9999`), we + represent them using a positive or negative infinity and the returned `ec` is set to `std::errc::result_out_of_range`. +* For values that are very close to zero (e.g., `1e-9999`), we represent them + using a positive or negative zero and the returned `ec` is set to + `std::errc::result_out_of_range`. We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems. @@ -401,6 +408,23 @@ except `fast_float::integer_times_pow10()` does not report out-of-range errors, underflows to zero or overflows to infinity when the resulting value is out of range. +You can use template overloads to get the result converted to different +supported floating-point types: `float`, `double`, etc. +For example, to get result as `float` use +`fast_float::integer_times_pow10()` specialization: +```C++ +const uint64_t W = 12345678; +const int Q = 23; +const float result = fast_float::integer_times_pow10(W, Q); +std::cout.precision(9); +std::cout << "float: " << W << " * 10^" << Q << " = " << result << " (" + << (result == 12345678e23f ? "==" : "!=") << "expected)\n"; +``` +outputs +``` +float: 12345678 * 10^23 = 1.23456782e+30 (==expected) +``` + Overloads of `fast_float::integer_times_pow10()` are provided for signed and unsigned integer types: `int64_t`, `uint64_t`, etc. @@ -443,7 +467,7 @@ framework](https://github.com/microsoft/LightGBM). Packages ------ -[![Packaging status](https://repology.org/badge/vertical-allrepos/fastfloat.svg)](https://repology.org/project/fastfloat/versions) +[![Packaging status](https://repology.org/badge/vertical-allrepos/fast-float.svg)](https://repology.org/project/fast-float/versions) ## References @@ -468,6 +492,7 @@ Packages [Jackson](https://github.com/FasterXML/jackson-core). * [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`. +* [There is a plain C port of the fast_float library](https://github.com/kolemannix/ffc.h) called ffc.h ## How fast is it? @@ -516,7 +541,7 @@ sufficiently recent version of CMake (3.11 or better at least): FetchContent_Declare( fast_float GIT_REPOSITORY https://github.com/fastfloat/fast_float.git - GIT_TAG tags/v8.1.0 + GIT_TAG tags/v8.2.5 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(fast_float) @@ -532,7 +557,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so: CPMAddPackage( NAME fast_float GITHUB_REPOSITORY "fastfloat/fast_float" - GIT_TAG v8.1.0) + GIT_TAG v8.2.5) ``` ## Using as single header @@ -544,7 +569,7 @@ if desired as described in the command line help. You may directly download automatically generated single-header files: - + ## Benchmarking @@ -598,6 +623,11 @@ long digits. The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published under the Apache 2.0 license. +## Stars + + +[![Star History Chart](https://api.star-history.com/svg?repos=fastfloat/fast_float&type=Date)](https://www.star-history.com/#fastfloat/fast_float&Date) + ## License diff --git a/3rdparty/fast_float/include/fast_float/ascii_number.h b/3rdparty/fast_float/include/fast_float/ascii_number.h index 5683cd47af..12c2fddcd3 100644 --- a/3rdparty/fast_float/include/fast_float/ascii_number.h +++ b/3rdparty/fast_float/include/fast_float/ascii_number.h @@ -32,7 +32,7 @@ template fastfloat_really_inline constexpr bool has_simd_opt() { // able to optimize it well. template fastfloat_really_inline constexpr bool is_integer(UC c) noexcept { - return !(c > UC('9') || c < UC('0')); + return (unsigned)(c - UC('0')) <= 9u; } fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { @@ -42,6 +42,11 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { (val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56; } +fastfloat_really_inline constexpr uint32_t byteswap_32(uint32_t val) { + return (val >> 24) | ((val >> 8) & 0x0000FF00u) | ((val << 8) & 0x00FF0000u) | + (val << 24); +} + // Read 8 UC into a u64. Truncates UC if not char. template fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t @@ -63,6 +68,25 @@ read8_to_u64(UC const *chars) { return val; } +// Read 4 UC into a u32. Truncates UC if not char. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t +read4_to_u32(UC const *chars) { + if (cpp20_and_in_constexpr() || !std::is_same::value) { + uint32_t val = 0; + for (int i = 0; i < 4; ++i) { + val |= uint32_t(uint8_t(*chars)) << (i * 8); + ++chars; + } + return val; + } + uint32_t val; + ::memcpy(&val, chars, sizeof(uint32_t)); +#if FASTFLOAT_IS_BIG_ENDIAN == 1 + val = byteswap_32(val); +#endif + return val; +} #ifdef FASTFLOAT_SSE2 fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) { @@ -144,6 +168,18 @@ is_made_of_eight_digits_fast(uint64_t val) noexcept { 0x8080808080808080)); } +fastfloat_really_inline constexpr bool +is_made_of_four_digits_fast(uint32_t val) noexcept { + return !((((val + 0x46464646) | (val - 0x30303030)) & 0x80808080)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t +parse_four_digits_unrolled(uint32_t val) noexcept { + val -= 0x30303030; + val = (val * 10) + (val >> 8); + return (((val & 0x00FF00FF) * 0x00640001) >> 16) & 0xFFFF; +} + #ifdef FASTFLOAT_HAS_SIMD // Call this if chars might not be 8 digits. @@ -509,6 +545,148 @@ parse_int_string(UC const *p, UC const *pend, T &value, UC const *const start_digits = p; + FASTFLOAT_IF_CONSTEXPR17((std::is_same::value)) { + if (base == 10) { + const size_t len = (size_t)(pend - p); + if (len == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + uint32_t digits; + +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST + if (std::is_constant_evaluated()) { + uint8_t str[4]{}; + for (size_t j = 0; j < 4 && j < len; ++j) { + str[j] = static_cast(p[j]); + } + digits = std::bit_cast(str); +#if FASTFLOAT_IS_BIG_ENDIAN + digits = byteswap_32(digits); +#endif + } +#else + if (false) { + } +#endif + else if (len >= 4) { + ::memcpy(&digits, p, 4); +#if FASTFLOAT_IS_BIG_ENDIAN + digits = byteswap_32(digits); +#endif + } else { + uint32_t b0 = static_cast(p[0]); + uint32_t b1 = (len > 1) ? static_cast(p[1]) : 0xFFu; + uint32_t b2 = (len > 2) ? static_cast(p[2]) : 0xFFu; + uint32_t b3 = 0xFFu; + digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24); + } + + uint32_t magic = + ((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u; + uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32 + uint32_t nd = (tz == 32) ? 4 : (tz >> 3); + nd = (uint32_t)(nd < len ? nd : len); + if (nd == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + return answer; + } + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + if (nd > 3) { + const UC *q = p + nd; + size_t rem = len - nd; + while (rem) { + if (*q < UC('0') || *q > UC('9')) + break; + ++q; + --rem; + } + answer.ec = std::errc::result_out_of_range; + answer.ptr = q; + return answer; + } + + digits ^= 0x30303030u; + digits <<= ((4 - nd) * 8); + + uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) | + ((digits << 8) & 0xff0000); + if (check > 0x00020505) { + answer.ec = std::errc::result_out_of_range; + answer.ptr = p + nd; + return answer; + } + value = (uint8_t)((0x640a01 * digits) >> 24); + answer.ec = std::errc(); + answer.ptr = p + nd; + return answer; + } + } + + FASTFLOAT_IF_CONSTEXPR17((std::is_same::value)) { + if (base == 10) { + const size_t len = size_t(pend - p); + if (len == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + if (len >= 4) { + uint32_t digits = read4_to_u32(p); + if (is_made_of_four_digits_fast(digits)) { + uint32_t v = parse_four_digits_unrolled(digits); + if (len >= 5 && is_integer(p[4])) { + v = v * 10 + uint32_t(p[4] - '0'); + if (len >= 6 && is_integer(p[5])) { + answer.ec = std::errc::result_out_of_range; + const UC *q = p + 5; + while (q != pend && is_integer(*q)) { + q++; + } + answer.ptr = q; + return answer; + } + if (v > 65535) { + answer.ec = std::errc::result_out_of_range; + answer.ptr = p + 5; + return answer; + } + value = uint16_t(v); + answer.ec = std::errc(); + answer.ptr = p + 5; + return answer; + } + // 4 digits + value = uint16_t(v); + answer.ec = std::errc(); + answer.ptr = p + 4; + return answer; + } + } + } + } + uint64_t i = 0; if (base == 10) { loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible diff --git a/3rdparty/fast_float/include/fast_float/digit_comparison.h b/3rdparty/fast_float/include/fast_float/digit_comparison.h index d7ef3d9acc..c2c83b0cf5 100644 --- a/3rdparty/fast_float/include/fast_float/digit_comparison.h +++ b/3rdparty/fast_float/include/fast_float/digit_comparison.h @@ -1,7 +1,6 @@ #ifndef FASTFLOAT_DIGIT_COMPARISON_H #define FASTFLOAT_DIGIT_COMPARISON_H -#include #include #include #include @@ -38,11 +37,8 @@ constexpr static uint64_t powers_of_ten_uint64[] = {1UL, // this algorithm is not even close to optimized, but it has no practical // effect on performance: in order to have a faster algorithm, we'd need // to slow down performance for faster algorithms, and this is still fast. -template fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t -scientific_exponent(parsed_number_string_t &num) noexcept { - uint64_t mantissa = num.mantissa; - int32_t exponent = int32_t(num.exponent); +scientific_exponent(uint64_t mantissa, int32_t exponent) noexcept { while (mantissa >= 10000) { mantissa /= 10000; exponent += 4; @@ -112,7 +108,7 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am, if (-am.power2 >= mantissa_shift) { // have a denormal float int32_t shift = -am.power2 + 1; - cb(am, std::min(shift, 64)); + cb(am, (shift < 64 ? shift : 64)); // check for round-up: if rounding-nearest carried us to the hidden bit. am.power2 = (am.mantissa < (uint64_t(1) << binary_format::mantissa_explicit_bits())) @@ -398,7 +394,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp( FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); } - // compare digits, and use it to director rounding + // compare digits, and use it to direct rounding int ord = real_digits.compare(theor_digits); adjusted_mantissa answer = am; round(answer, [ord](adjusted_mantissa &a, int32_t shift) { @@ -419,7 +415,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp( return answer; } -// parse the significant digits as a big integer to unambiguously round the +// parse the significant digits as a big integer to unambiguously round // the significant digits. here, we are trying to determine how to round // an extended float representation close to `b+h`, halfway between `b` // (the float rounded-down) and `b+u`, the next positive float. this @@ -438,7 +434,8 @@ digit_comp(parsed_number_string_t &num, adjusted_mantissa am) noexcept { // remove the invalid exponent bias am.power2 -= invalid_am_bias; - int32_t sci_exp = scientific_exponent(num); + int32_t sci_exp = + scientific_exponent(num.mantissa, static_cast(num.exponent)); size_t max_digits = binary_format::max_digits(); size_t digits = 0; bigint bigmant; diff --git a/3rdparty/fast_float/include/fast_float/fast_float.h b/3rdparty/fast_float/include/fast_float/fast_float.h index a190d7c823..eb822f58ed 100644 --- a/3rdparty/fast_float/include/fast_float/fast_float.h +++ b/3rdparty/fast_float/include/fast_float/fast_float.h @@ -63,6 +63,20 @@ integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept; FASTFLOAT_CONSTEXPR20 inline double integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept; +/** + * This function is a template overload of `integer_times_pow10()` + * that returns a floating-point value of type `T` that is one of + * supported floating-point types (e.g. `double`, `float`). + */ +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value, T>::type + integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept; +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value, T>::type + integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept; + /** * from_chars for integer types. */ diff --git a/3rdparty/fast_float/include/fast_float/float_common.h b/3rdparty/fast_float/include/fast_float/float_common.h index 62d199ca82..403eea1f20 100644 --- a/3rdparty/fast_float/include/fast_float/float_common.h +++ b/3rdparty/fast_float/include/fast_float/float_common.h @@ -2,6 +2,7 @@ #define FASTFLOAT_FLOAT_COMMON_H #include +#include #include #include #include @@ -16,8 +17,8 @@ #include "constexpr_feature_detect.h" #define FASTFLOAT_VERSION_MAJOR 8 -#define FASTFLOAT_VERSION_MINOR 1 -#define FASTFLOAT_VERSION_PATCH 0 +#define FASTFLOAT_VERSION_MINOR 2 +#define FASTFLOAT_VERSION_PATCH 5 #define FASTFLOAT_STRINGIZE_IMPL(x) #x #define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) @@ -267,18 +268,147 @@ struct is_supported_char_type > { }; +template +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp3(UC const *actual_mixedcase, + UC const *expected_lowercase) { + uint64_t mask{0}; + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + } + else { + return false; + } + + uint64_t val1{0}, val2{0}; + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < 3; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1 || sizeof(UC) == 2) { + ::memcpy(&val1, actual_mixedcase, 3 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 3 * sizeof(UC)); + val1 |= mask; + val2 |= mask; + return val1 == val2; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[2] | 32) == (expected_lowercase[2]); + } + else { + return false; + } + } +} + +template +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp5(UC const *actual_mixedcase, + UC const *expected_lowercase) { + uint64_t mask{0}; + uint64_t val1{0}, val2{0}; + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < 5; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { + mask = 0x2020202020202020; + ::memcpy(&val1, actual_mixedcase, 5 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 5 * sizeof(UC)); + val1 |= mask; + val2 |= mask; + return val1 == val2; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + ::memcpy(&val1, actual_mixedcase, 4 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 4 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + ::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + ::memcpy(&val1, actual_mixedcase + 2, 2 * sizeof(UC)); + ::memcpy(&val2, expected_lowercase + 2, 2 * sizeof(UC)); + val1 |= mask; + if (val1 != val2) { + return false; + } + return (actual_mixedcase[4] | 32) == (expected_lowercase[4]); + } + else { + return false; + } + } +} + // Compares two ASCII strings in a case insensitive manner. template inline FASTFLOAT_CONSTEXPR14 bool fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, size_t length) { - for (size_t i = 0; i < length; ++i) { - UC const actual = actual_mixedcase[i]; - if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) { - return false; - } + uint64_t mask{0}; + FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) { + mask = 0x0020002000200020; + } + else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) { + mask = 0x0000002000000020; + } + else { + return false; + } + + if (cpp20_and_in_constexpr()) { + for (size_t i = 0; i < length; i++) { + if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) { + return false; + } + } + return true; + } else { + uint64_t val1{0}, val2{0}; + size_t sz{8 / (sizeof(UC))}; + for (size_t i = 0; i < length; i += sz) { + val1 = val2 = 0; + sz = sz < (length - i) ? sz : length - i; + ::memcpy(&val1, actual_mixedcase + i, sz * sizeof(UC)); + ::memcpy(&val2, expected_lowercase + i, sz * sizeof(UC)); + val1 |= mask; + val2 |= mask; + if (val1 != val2) { + return false; + } + } + return true; } - return true; } #ifndef FLT_EVAL_METHOD @@ -362,6 +492,52 @@ leading_zeroes(uint64_t input_num) { #endif } +/* Helper C++14 constexpr generic implementation of countr_zero for 32-bit */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int +countr_zero_generic_32(uint32_t input_num) { + if (input_num == 0) { + return 32; + } + int last_bit = 0; + if (!(input_num & 0x0000FFFF)) { + input_num >>= 16; + last_bit |= 16; + } + if (!(input_num & 0x00FF)) { + input_num >>= 8; + last_bit |= 8; + } + if (!(input_num & 0x0F)) { + input_num >>= 4; + last_bit |= 4; + } + if (!(input_num & 0x3)) { + input_num >>= 2; + last_bit |= 2; + } + if (!(input_num & 0x1)) { + last_bit |= 1; + } + return last_bit; +} + +/* count trailing zeroes for 32-bit integers */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int +countr_zero_32(uint32_t input_num) { + if (cpp20_and_in_constexpr()) { + return countr_zero_generic_32(input_num); + } +#ifdef FASTFLOAT_VISUAL_STUDIO + unsigned long trailing_zero = 0; + if (_BitScanForward(&trailing_zero, input_num)) { + return (int)trailing_zero; + } + return 32; +#else + return input_num == 0 ? 32 : __builtin_ctz(input_num); +#endif +} + // slow emulation routine for 32-bit fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) { return x * (uint64_t)y; @@ -406,8 +582,8 @@ full_multiplication(uint64_t a, uint64_t b) { // But MinGW on ARM64 doesn't have native support for 64-bit multiplications answer.high = __umulh(a, b); answer.low = a * b; -#elif defined(FASTFLOAT_32BIT) || \ - (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64)) +#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__) && \ + !defined(_M_ARM64) && !defined(__GNUC__)) answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 #elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) __uint128_t r = ((__uint128_t)a) * b; @@ -1166,6 +1342,9 @@ static_assert(std::is_same, uint64_t>::value, static_assert( std::numeric_limits::is_iec559, "std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)"); + +template <> +struct binary_format : public binary_format {}; #endif // __STDCPP_FLOAT64_T__ #ifdef __STDCPP_FLOAT32_T__ @@ -1174,6 +1353,9 @@ static_assert(std::is_same, uint32_t>::value, static_assert( std::numeric_limits::is_iec559, "std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)"); + +template <> +struct binary_format : public binary_format {}; #endif // __STDCPP_FLOAT32_T__ #ifdef __STDCPP_FLOAT16_T__ @@ -1245,7 +1427,6 @@ constexpr chars_format adjust_for_feature_macros(chars_format fmt) { ; } } // namespace detail - } // namespace fast_float #endif diff --git a/3rdparty/fast_float/include/fast_float/parse_number.h b/3rdparty/fast_float/include/fast_float/parse_number.h index a44fef0b56..ff9c53d09f 100644 --- a/3rdparty/fast_float/include/fast_float/parse_number.h +++ b/3rdparty/fast_float/include/fast_float/parse_number.h @@ -35,7 +35,7 @@ from_chars_result_t ++first; } if (last - first >= 3) { - if (fastfloat_strncasecmp(first, str_const_nan(), 3)) { + if (fastfloat_strncasecmp3(first, str_const_nan())) { answer.ptr = (first += 3); value = minusSign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); @@ -54,9 +54,9 @@ from_chars_result_t } return answer; } - if (fastfloat_strncasecmp(first, str_const_inf(), 3)) { + if (fastfloat_strncasecmp3(first, str_const_inf())) { if ((last - first >= 8) && - fastfloat_strncasecmp(first + 3, str_const_inf() + 3, 5)) { + fastfloat_strncasecmp5(first + 3, str_const_inf() + 3)) { answer.ptr = first + 8; } else { answer.ptr = first + 3; @@ -155,7 +155,7 @@ template <> struct from_chars_caller { // if std::float32_t is defined, and we are in C++23 mode; macro set for // float32; set value to float due to equivalence between float and // float32_t - float val; + float val = 0.0f; auto ret = from_chars_advanced(first, last, val, options); value = val; return ret; @@ -172,7 +172,7 @@ template <> struct from_chars_caller { // if std::float64_t is defined, and we are in C++23 mode; macro set for // float64; set value as double due to equivalence between double and // float64_t - double val; + double val = 0.0; auto ret = from_chars_advanced(first, last, val, options); value = val; return ret; @@ -251,7 +251,7 @@ clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative, * parsing options or other parsing custom function implemented by user. */ template -FASTFLOAT_CONSTEXPR20 from_chars_result_t +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_advanced(parsed_number_string_t &pns, T &value) noexcept { static_assert(is_supported_float_type::value, "only some floating-point types are supported"); @@ -290,7 +290,7 @@ from_chars_advanced(parsed_number_string_t &pns, T &value) noexcept { } template -FASTFLOAT_CONSTEXPR20 from_chars_result_t +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_float_advanced(UC const *first, UC const *last, T &value, parse_options_t options) noexcept { @@ -344,44 +344,79 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept { return from_chars_advanced(first, last, value, options); } -FASTFLOAT_CONSTEXPR20 inline double -integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept { - double value; +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value, T>::type + integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept { + T value; if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value)) return value; adjusted_mantissa am = - compute_float>(decimal_exponent, mantissa); + compute_float>(decimal_exponent, mantissa); to_float(false, am, value); return value; } -FASTFLOAT_CONSTEXPR20 inline double -integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept { +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value, T>::type + integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept { const bool is_negative = mantissa < 0; const uint64_t m = static_cast(is_negative ? -mantissa : mantissa); - double value; + T value; if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value)) return value; - adjusted_mantissa am = - compute_float>(decimal_exponent, m); + adjusted_mantissa am = compute_float>(decimal_exponent, m); to_float(is_negative, am, value); return value; } +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(mantissa, decimal_exponent); +} + +FASTFLOAT_CONSTEXPR20 inline double +integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(mantissa, decimal_exponent); +} + // the following overloads are here to avoid surprising ambiguity for int, // unsigned, etc. +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value && + std::is_integral::value && + !std::is_signed::value, + T>::type + integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), + decimal_exponent); +} + +template +FASTFLOAT_CONSTEXPR20 + typename std::enable_if::value && + std::is_integral::value && + std::is_signed::value, + T>::type + integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { + return integer_times_pow10(static_cast(mantissa), + decimal_exponent); +} + template -FASTFLOAT_CONSTEXPR20 inline typename std::enable_if< +FASTFLOAT_CONSTEXPR20 typename std::enable_if< std::is_integral::value && !std::is_signed::value, double>::type integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); } template -FASTFLOAT_CONSTEXPR20 inline typename std::enable_if< +FASTFLOAT_CONSTEXPR20 typename std::enable_if< std::is_integral::value && std::is_signed::value, double>::type integer_times_pow10(Int mantissa, int decimal_exponent) noexcept { return integer_times_pow10(static_cast(mantissa), decimal_exponent); @@ -421,7 +456,7 @@ template struct from_chars_advanced_caller { template <> struct from_chars_advanced_caller<1> { template - FASTFLOAT_CONSTEXPR20 static from_chars_result_t + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, T &value, parse_options_t options) noexcept { return from_chars_float_advanced(first, last, value, options); @@ -430,7 +465,7 @@ template <> struct from_chars_advanced_caller<1> { template <> struct from_chars_advanced_caller<2> { template - FASTFLOAT_CONSTEXPR20 static from_chars_result_t + fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t call(UC const *first, UC const *last, T &value, parse_options_t options) noexcept { return from_chars_int_advanced(first, last, value, options); @@ -438,7 +473,7 @@ template <> struct from_chars_advanced_caller<2> { }; template -FASTFLOAT_CONSTEXPR20 from_chars_result_t +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t from_chars_advanced(UC const *first, UC const *last, T &value, parse_options_t options) noexcept { return from_chars_advanced_caller< diff --git a/3rdparty/lzma/include/7zFile.h b/3rdparty/lzma/include/7zFile.h index f5069cd9ee..c842f919b4 100644 --- a/3rdparty/lzma/include/7zFile.h +++ b/3rdparty/lzma/include/7zFile.h @@ -1,12 +1,11 @@ /* 7zFile.h -- File IO -2023-03-05 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_FILE_H #define ZIP7_INC_FILE_H #ifdef _WIN32 #define USE_WINDOWS_FILE -// #include #endif #ifdef USE_WINDOWS_FILE diff --git a/3rdparty/lzma/include/7zTypes.h b/3rdparty/lzma/include/7zTypes.h index 5b77420a3b..8aaabc8fbc 100644 --- a/3rdparty/lzma/include/7zTypes.h +++ b/3rdparty/lzma/include/7zTypes.h @@ -1,5 +1,5 @@ /* 7zTypes.h -- Basic types -2024-01-24 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #ifndef ZIP7_7Z_TYPES_H #define ZIP7_7Z_TYPES_H @@ -46,8 +46,9 @@ typedef int SRes; #ifdef _MSC_VER + #define MY_ALIGN_IN_STRUCT(n) __declspec(align(n)) #if _MSC_VER > 1200 - #define MY_ALIGN(n) __declspec(align(n)) + #define MY_ALIGN(n) MY_ALIGN_IN_STRUCT(n) #else #define MY_ALIGN(n) #endif @@ -58,6 +59,7 @@ typedef int SRes; #define MY_ALIGN(n) alignas(n) */ #define MY_ALIGN(n) __attribute__ ((aligned(n))) + #define MY_ALIGN_IN_STRUCT(n) MY_ALIGN(n) #endif diff --git a/3rdparty/lzma/include/7zVersion.h b/3rdparty/lzma/include/7zVersion.h index 72733f7fae..387a91c01c 100644 --- a/3rdparty/lzma/include/7zVersion.h +++ b/3rdparty/lzma/include/7zVersion.h @@ -1,7 +1,7 @@ -#define MY_VER_MAJOR 25 -#define MY_VER_MINOR 0 +#define MY_VER_MAJOR 26 +#define MY_VER_MINOR 1 #define MY_VER_BUILD 0 -#define MY_VERSION_NUMBERS "25.00" +#define MY_VERSION_NUMBERS "26.01" #define MY_VERSION MY_VERSION_NUMBERS #ifdef MY_CPU_NAME @@ -10,12 +10,12 @@ #define MY_VERSION_CPU MY_VERSION #endif -#define MY_DATE "2025-07-05" +#define MY_DATE "2026-04-27" #undef MY_COPYRIGHT #undef MY_VERSION_COPYRIGHT_DATE #define MY_AUTHOR_NAME "Igor Pavlov" #define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" -#define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2026 Igor Pavlov" #ifdef USE_COPYRIGHT_CR #define MY_COPYRIGHT MY_COPYRIGHT_CR diff --git a/3rdparty/lzma/include/7zWindows.h b/3rdparty/lzma/include/7zWindows.h index 42c6db8bfc..381159edf5 100644 --- a/3rdparty/lzma/include/7zWindows.h +++ b/3rdparty/lzma/include/7zWindows.h @@ -1,11 +1,17 @@ -/* 7zWindows.h -- StdAfx -2023-04-02 : Igor Pavlov : Public domain */ +/* 7zWindows.h -- Windows.h and related code +Igor Pavlov : Public domain */ #ifndef ZIP7_INC_7Z_WINDOWS_H #define ZIP7_INC_7Z_WINDOWS_H #ifdef _WIN32 +#if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026 +// and some another windows files need that option +// VS2026: wtypesbase.h: warning C4865: 'tagCLSCTX': the underlying type will change from 'int' to 'unsigned int' when '/Zc:enumTypes' is specified on the command line +#pragma warning(disable : 4865) +#endif + #if defined(__clang__) # pragma clang diagnostic push #endif diff --git a/3rdparty/lzma/include/Alloc.h b/3rdparty/lzma/include/Alloc.h index 01bf6b7dd6..eedd295280 100644 --- a/3rdparty/lzma/include/Alloc.h +++ b/3rdparty/lzma/include/Alloc.h @@ -1,5 +1,5 @@ /* Alloc.h -- Memory allocation functions -2024-01-22 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_ALLOC_H #define ZIP7_INC_ALLOC_H @@ -25,40 +25,40 @@ void *MyRealloc(void *address, size_t size); void *z7_AlignedAlloc(size_t size); void z7_AlignedFree(void *p); +extern const ISzAlloc g_Alloc; +extern const ISzAlloc g_AlignedAlloc; + #ifdef _WIN32 + void *MidAlloc(size_t size); + void MidFree(void *address); + extern const ISzAlloc g_MidAlloc; +#else + #define MidAlloc(size) z7_AlignedAlloc(size) + #define MidFree(address) z7_AlignedFree(address) + #define g_MidAlloc g_AlignedAlloc +#endif #ifdef Z7_LARGE_PAGES -void SetLargePageSize(void); -#endif -void *MidAlloc(size_t size); -void MidFree(void *address); -void *BigAlloc(size_t size); -void BigFree(void *address); - -/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */ +#define Z7_LARGE_PAGES_FLAG_USE_HUGEPAGE (1 << 0) // PAGE_ALIGNED / MADV_HUGEPAGE +#define Z7_LARGE_PAGES_FLAG_NO_PAGECODE (1 << 1) // no PAGE_ALIGNED / no madvise +#define Z7_LARGE_PAGES_FLAG_NO_MADVISE (1 << 2) // PAGE_ALIGNED / no madvise : for THP=always +#define Z7_LARGE_PAGES_FLAG_NO_HUGEPAGE (1 << 3) // PAGE_ALIGNED / MADV_NOHUGEPAGE +#define Z7_LARGE_PAGES_FLAG_FAIL_STOP (1 << 15) // for benchmarks +#define Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE (1 << 16) +#define Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD (1 << 17) +void z7_LargePage_Set(UInt32 flags, size_t pageSize, size_t threshold); + + void *BigAlloc(size_t size); + void BigFree(void *address); + extern const ISzAlloc g_BigAlloc; #else - -#define MidAlloc(size) z7_AlignedAlloc(size) -#define MidFree(address) z7_AlignedFree(address) -#define BigAlloc(size) z7_AlignedAlloc(size) -#define BigFree(address) z7_AlignedFree(address) - + #define BigAlloc(size) MidAlloc(size) + #define BigFree(address) MidFree(address) + #define g_BigAlloc g_MidAlloc #endif -extern const ISzAlloc g_Alloc; - -#ifdef _WIN32 -extern const ISzAlloc g_BigAlloc; -extern const ISzAlloc g_MidAlloc; -#else -#define g_BigAlloc g_AlignedAlloc -#define g_MidAlloc g_AlignedAlloc -#endif - -extern const ISzAlloc g_AlignedAlloc; - typedef struct { diff --git a/3rdparty/lzma/include/Compiler.h b/3rdparty/lzma/include/Compiler.h index b266b277bd..a3577b2545 100644 --- a/3rdparty/lzma/include/Compiler.h +++ b/3rdparty/lzma/include/Compiler.h @@ -54,6 +54,12 @@ #pragma GCC diagnostic ignored "-Wexcess-padding" #endif +#if defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 21 +// warning: function MyAlloc might be an allocator wrapper +// clang in xcode: clang 21.0.0 +#pragma GCC diagnostic ignored "-Wallocator-wrappers" +#endif + #if __clang_major__ >= 16 #pragma GCC diagnostic ignored "-Wunsafe-buffer-usage" #endif @@ -72,7 +78,7 @@ #endif // __clang__ -#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16 +#if defined(__clang__) && __clang_major__ >= 16 // #pragma GCC diagnostic ignored "-Wcast-function-type-strict" #define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \ _Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"") diff --git a/3rdparty/lzma/include/CpuArch.h b/3rdparty/lzma/include/CpuArch.h index 1690a5b616..348db0a4c9 100644 --- a/3rdparty/lzma/include/CpuArch.h +++ b/3rdparty/lzma/include/CpuArch.h @@ -31,7 +31,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #define MY_CPU_NAME "x32" #define MY_CPU_SIZEOF_POINTER 4 #else - #define MY_CPU_NAME "x64" + #if defined(__APX_EGPR__) || defined(__EGPR__) + #define MY_CPU_NAME "x64-apx" + #define MY_CPU_AMD64_APX + #else + #define MY_CPU_NAME "x64" + #endif #define MY_CPU_SIZEOF_POINTER 8 #endif #define MY_CPU_64BIT @@ -249,11 +254,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers. #endif +// _LITTLE_ENDIAN macro can be defined for big-endian platform with some compilers + #if defined(MY_CPU_X86_OR_AMD64) \ || defined(MY_CPU_ARM_LE) \ || defined(MY_CPU_ARM64_LE) \ || defined(MY_CPU_IA64_LE) \ - || defined(_LITTLE_ENDIAN) \ || defined(__LITTLE_ENDIAN__) \ || defined(__ARMEL__) \ || defined(__THUMBEL__) \ @@ -596,8 +602,20 @@ problem-4 : performace: #define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); } #define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); } +// gcc and clang for powerpc can transform load byte access to load reverse word access. +// sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow +#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT) +#define GetUi64a(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p)) +#else #define GetUi64a(p) GetUi64(p) +#endif + +#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) +#define GetUi32a(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p)) +#else #define GetUi32a(p) GetUi32(p) +#endif + #define GetUi16a(p) GetUi16(p) #define SetUi32a(p, v) SetUi32(p, v) #define SetUi16a(p, v) SetUi16(p, v) diff --git a/3rdparty/lzma/include/Precomp.h b/3rdparty/lzma/include/Precomp.h index 7747fdd74c..83b720e115 100644 --- a/3rdparty/lzma/include/Precomp.h +++ b/3rdparty/lzma/include/Precomp.h @@ -1,5 +1,5 @@ /* Precomp.h -- precompilation file -2024-01-25 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #ifndef ZIP7_INC_PRECOMP_H #define ZIP7_INC_PRECOMP_H @@ -40,18 +40,18 @@ #endif */ +#ifndef Z7_LARGE_PAGES +#if !defined(Z7_NO_LARGE_PAGES) && !defined(UNDER_CE) +#define Z7_LARGE_PAGES 1 +#endif +#endif + #ifdef _WIN32 /* this "Precomp.h" file must be included before , if we want to define _WIN32_WINNT before . */ -#ifndef Z7_LARGE_PAGES -#ifndef Z7_NO_LARGE_PAGES -#define Z7_LARGE_PAGES 1 -#endif -#endif - #ifndef Z7_LONG_PATH #ifndef Z7_NO_LONG_PATH #define Z7_LONG_PATH 1 diff --git a/3rdparty/lzma/src/7zArcIn.c b/3rdparty/lzma/src/7zArcIn.c index 23f2949922..4dc3ba105c 100644 --- a/3rdparty/lzma/src/7zArcIn.c +++ b/3rdparty/lzma/src/7zArcIn.c @@ -1,5 +1,5 @@ /* 7zArcIn.c -- 7z Input functions -2023-09-07 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -289,9 +289,9 @@ static SRes WaitId(CSzData *sd, UInt32 id) } } -static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v) +static SRes RememberBitVector(CSzData *sd, size_t numItems, const Byte **v) { - const UInt32 numBytes = (numItems + 7) >> 3; + const size_t numBytes = (numItems + 7) >> 3; if (numBytes > sd->Size) return SZ_ERROR_ARCHIVE; *v = sd->Data; @@ -317,11 +317,11 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems) return sum; } -static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc) +static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, size_t numItems, Byte **v, ISzAllocPtr alloc) { Byte allAreDefined; Byte *v2; - const UInt32 numBytes = (numItems + 7) >> 3; + const size_t numBytes = (numItems + 7) >> 3; *v = NULL; SZ_READ_BYTE(allAreDefined) if (numBytes == 0) @@ -345,9 +345,9 @@ static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I return SZ_OK; } -static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { - UInt32 i; + size_t i; CSzData sd; UInt32 *vals; const Byte *defs; @@ -366,7 +366,7 @@ static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c return SZ_OK; } -static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) +static SRes ReadBitUi32s(CSzData *sd, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc) { SzBitUi32s_Free(crcs, alloc); RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc)) @@ -1027,42 +1027,39 @@ static SRes SzReadAndDecodePackedStreams( return SZ_OK; } +// (size & 1) == 0 +// (data) is aligned for 2-bytes static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets) { - size_t pos = 0; + const Byte *p, *lim; *offsets++ = 0; if (numFiles == 0) return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE; if (size < 2) return SZ_ERROR_ARCHIVE; - if (data[size - 2] != 0 || data[size - 1] != 0) + lim = data + size; + if (*(const UInt16 *)(const void *)(lim - 2)) return SZ_ERROR_ARCHIVE; + p = data; do { - const Byte *p; - if (pos == size) + if (p >= lim) return SZ_ERROR_ARCHIVE; - for (p = data + pos; - #ifdef _WIN32 - *(const UInt16 *)(const void *)p != 0 - #else - p[0] != 0 || p[1] != 0 - #endif - ; p += 2); - pos = (size_t)(p - data) + 2; - *offsets++ = (pos >> 1); + for (; *(const UInt16 *)(const void *)p; p += 2); + p += 2; + *offsets++ = (size_t)(p - data) >> 1; } while (--numFiles); - return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE; + return (p == lim) ? SZ_OK : SZ_ERROR_ARCHIVE; } -static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num, +static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, size_t num, CSzData *sd2, const CBuf *tempBufs, UInt32 numTempBufs, ISzAllocPtr alloc) { CSzData sd; - UInt32 i; + size_t i; CNtfsFileTime *vals; Byte *defs; Byte external; @@ -1215,6 +1212,7 @@ static SRes SzReadHeader2( { namesSize = (size_t)size - 1; namesData = sd->Data; + SKIP_DATA(sd, namesSize) } else { @@ -1226,15 +1224,11 @@ static SRes SzReadHeader2( namesSize = (tempBufs)[index].size; } - if ((namesSize & 1) != 0) + if (namesSize & 1) return SZ_ERROR_ARCHIVE; MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain) MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain) RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets)) - if (external == 0) - { - SKIP_DATA(sd, namesSize) - } break; } case k7zIdEmptyStream: diff --git a/3rdparty/lzma/src/Alloc.c b/3rdparty/lzma/src/Alloc.c index 63e1a121e7..419fa37504 100644 --- a/3rdparty/lzma/src/Alloc.c +++ b/3rdparty/lzma/src/Alloc.c @@ -1,5 +1,5 @@ /* Alloc.c -- Memory allocation functions -2024-02-18 : Igor Pavlov : Public domain */ +: Igor Pavlov : Public domain */ #include "Precomp.h" @@ -24,8 +24,6 @@ #endif // #define SZ_ALLOC_DEBUG -/* #define SZ_ALLOC_DEBUG */ - /* use SZ_ALLOC_DEBUG to debug alloc/free operations */ #ifdef SZ_ALLOC_DEBUG @@ -34,9 +32,10 @@ static int g_allocCount = 0; #ifdef _WIN32 static int g_allocCountMid = 0; +#ifdef Z7_LARGE_PAGES static int g_allocCountBig = 0; #endif - +#endif #define CONVERT_INT_TO_STR(charType, tempSize) \ char temp[tempSize]; unsigned i = 0; \ @@ -140,8 +139,10 @@ static void PrintAddr(void *p) #else #ifdef _WIN32 +#ifdef Z7_LARGE_PAGES #define PRINT_ALLOC(name, cnt, size, ptr) #endif +#endif #define PRINT_FREE(name, cnt, ptr) #define Print(s) #define PrintLn() @@ -245,6 +246,7 @@ void MidFree(void *address) } #ifdef Z7_LARGE_PAGES +// #pragma message("Z7_LARGE_PAGES") #ifdef MEM_LARGE_PAGES #define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES @@ -253,32 +255,14 @@ void MidFree(void *address) #endif extern -SIZE_T g_LargePageSize; -SIZE_T g_LargePageSize = 0; -typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); - -void SetLargePageSize(void) -{ - SIZE_T size; -#ifdef Z7_USE_DYN_GetLargePageMinimum -Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION - - const - Func_GetLargePageMinimum fn = - (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), - "GetLargePageMinimum"); - if (!fn) - return; - size = fn(); -#else - size = GetLargePageMinimum(); -#endif - if (size == 0 || (size & (size - 1)) != 0) - return; - g_LargePageSize = size; -} - -#endif // Z7_LARGE_PAGES +size_t g_LargePageSize; +size_t g_LargePageSize = 0; +extern +size_t g_LargePageThresholdMin; +size_t g_LargePageThresholdMin = 0; +extern +UInt32 g_LargePageFlags; +UInt32 g_LargePageFlags = 0; void *BigAlloc(size_t size) { @@ -289,12 +273,10 @@ void *BigAlloc(size_t size) #ifdef Z7_LARGE_PAGES { - SIZE_T ps = g_LargePageSize; - if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) + const size_t ps = g_LargePageSize - 1; + if (ps < (1u << 30) && size > g_LargePageThresholdMin) { - size_t size2; - ps--; - size2 = (size + ps) & ~ps; + const size_t size2 = (size + ps) & ~ps; if (size2 >= size) { void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE); @@ -303,6 +285,8 @@ void *BigAlloc(size_t size) PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p) return p; } + if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP) + return p; } } } @@ -317,6 +301,7 @@ void BigFree(void *address) MidFree(address); } +#endif // Z7_LARGE_PAGES #endif // _WIN32 @@ -327,9 +312,12 @@ const ISzAlloc g_Alloc = { SzAlloc, SzFree }; #ifdef _WIN32 static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); } static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); } +const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; +#endif + +#if defined(Z7_LARGE_PAGES) static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); } static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); } -const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; #endif @@ -371,10 +359,16 @@ typedef #endif -#if !defined(_WIN32) \ - && (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \ - || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) +#ifndef _WIN32 +#include // for _POSIX_ADVISORY_INFO : for some linux +#if (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \ + || defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) \ + || defined(_POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO >= 200112L) \ + || defined(__APPLE__) \ + /* || defined(__linux__) */) #define USE_posix_memalign + // #pragma message("USE_posix_memalign") +#endif #endif #ifndef USE_posix_memalign @@ -488,6 +482,181 @@ static void SzAlignedFree(ISzAllocPtr pp, void *address) #endif } +#ifndef _WIN32 + +#ifdef Z7_LARGE_PAGES + +#if 0 // 1 for debug + #include + #include // for strerror() + #define PRF(x) x +#else + #define PRF(x) +#endif + +#ifdef USE_posix_memalign + /* madvise(): + glibc <= 2.19 : _BSD_SOURCE + glibc > 2.19 : _DEFAULT_SOURCE + */ + /* && (defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)) */ +#if 1 && !defined(Z7_NO_MADVISE) && \ + (defined(__linux__) || defined(__unix__) || defined(__APPLE__)) +#include // for madvise +// #pragma message("sys/mman.h") +#if (defined(MADV_HUGEPAGE) && defined(MADV_NOHUGEPAGE)) + #define Z7_USE_BIG_ALLOC_MADVISE + // #pragma message("Z7_USE_BIG_ALLOC_MADVISE") +#endif +#endif +#endif // USE_posix_memalign + +#ifdef Z7_USE_BIG_ALLOC_MADVISE +#define LARGE_PAGE_SIZE_DEFAULT (1 << 21) +#else +#define LARGE_PAGE_SIZE_DEFAULT 0 +#endif + +extern +size_t g_LargePageSize; +size_t g_LargePageSize = LARGE_PAGE_SIZE_DEFAULT; +extern +size_t g_LargePageThresholdMin; +size_t g_LargePageThresholdMin = LARGE_PAGE_SIZE_DEFAULT / 2; +extern +UInt32 g_LargePageFlags; +UInt32 g_LargePageFlags = 0; + +void *BigAlloc(size_t size) +{ + if (size == 0) + return NULL; +#ifdef USE_posix_memalign + { + const size_t pageSize = g_LargePageSize; + void *buf = NULL; // on Linux (and other systems), posix_memalign() does not modify memptr on failure (POSIX.1-2008 TC2). + PRF(printf("\nBigAlloc 0x%08x=%5uMB", (unsigned)(size), (unsigned)(size >> 20));) + if (pageSize && size > g_LargePageThresholdMin) + { + int res; + const size_t mask = pageSize - 1; + /* we can allocate aligned size, so data at the end of buffer also will use huge page + if (size2 for madvise() is not aligned for huge page size) + { Last data block will use small pages. It reduces memory allocation, + but last data block with small pages can work slower. + It's useful, if we have very large HUGE_PAGE: 32MB or 512MB. } + */ + size_t size2 = (size + mask) & ~mask; + if (size2 < size || (size & mask) <= g_LargePageThresholdMin) + size2 = size; + res = posix_memalign(&buf, pageSize, size2); + PRF(printf(" posix_memalign size=0x%08x=%5uMB align=%u", + (unsigned)(size2), (unsigned)(size2 >> 20), (unsigned)pageSize);) + PRF(printf(" buf=%p", (void *)buf);) + if (res == 0) + { +#ifdef Z7_USE_BIG_ALLOC_MADVISE + if ((g_LargePageFlags & Z7_LARGE_PAGES_FLAG_NO_MADVISE) == 0) + { + // Advise the kernel to use huge pages for this memory range + // MADV_HUGEPAGE / MADV_NOHUGEPAGE : since Linux 2.6.38 + // madvise() only operates on whole pages, therefore addr must be page-aligned (4KB/8KB/16KB/64KB). + // The value of size is rounded up to a multiple of page size. + PRF(printf(" madvise g_LargePageFlags=%x", (unsigned)g_LargePageFlags);) + res = madvise(buf, size2, (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_NO_HUGEPAGE) ? MADV_NOHUGEPAGE : MADV_HUGEPAGE); + if (res) + { + PRF(printf("\nERROR res=%d, errno=%d=%s\n", res, (int)errno, strerror(errno));) + if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP) + { + free(buf); + return NULL; + } + } + } +#endif // Z7_USE_BIG_ALLOC_MADVISE + PRF(printf("\n");) + return buf; + } + PRF(printf("\nERROR res=%d=%s\n", res, strerror(res));) + if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP) + return NULL; + // (res == ENOMEM) "Out of memory" is possible, if pageSize is too big. + // so we do second attempt with smaller alignment + } + } +#endif // !USE_posix_memalign + PRF(printf(" z7_AlignedAlloc size=0x%08x=%5uMB\n", (unsigned)(size), (unsigned)(size >> 20));) + return z7_AlignedAlloc(size); +} + + +void BigFree(void *address) +{ + z7_AlignedFree(address); +} +#endif // Z7_LARGE_PAGES +#endif // !_WIN32 + + +#ifdef Z7_LARGE_PAGES +void z7_LargePage_Set(UInt32 flags, size_t pageSize, size_t threshold) +{ + g_LargePageFlags = flags; + +#ifdef _WIN32 + if ((flags & Z7_LARGE_PAGES_FLAG_USE_HUGEPAGE) == 0) + { + g_LargePageSize = 0; + g_LargePageThresholdMin = 0; + } + else + { + if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE) == 0) + { +#ifdef Z7_USE_DYN_GetLargePageMinimum + Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION +typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID); + const + Func_GetLargePageMinimum fn = + (Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), + "GetLargePageMinimum"); + if (fn) + pageSize = fn(); + else + pageSize = 0; +#else + pageSize = GetLargePageMinimum(); +#endif + if (pageSize & (pageSize - 1)) + pageSize = 0; + } + g_LargePageSize = pageSize; + if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD) == 0) + threshold = pageSize / 2; + g_LargePageThresholdMin = threshold; + } + +#else // !_WIN32 + + if (flags & Z7_LARGE_PAGES_FLAG_NO_PAGECODE) + { + g_LargePageSize = 0; + g_LargePageThresholdMin = 0; + } + else + { + if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE) == 0) + pageSize = LARGE_PAGE_SIZE_DEFAULT; + g_LargePageSize = pageSize; + if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD) == 0) + threshold = pageSize / 2; + g_LargePageThresholdMin = threshold; + } + // PRF(printf("\ng_LargePageSize=%x g_LargePageThresholdMin = %x g_LargePageFlags = %x", (unsigned)g_LargePageSize, (unsigned)g_LargePageThresholdMin, (unsigned)g_LargePageFlags);) +#endif // !_WIN32 +} +#endif // Z7_LARGE_PAGES const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; diff --git a/3rdparty/lzma/src/CpuArch.c b/3rdparty/lzma/src/CpuArch.c index 6e02551e2d..342280d0bc 100644 --- a/3rdparty/lzma/src/CpuArch.c +++ b/3rdparty/lzma/src/CpuArch.c @@ -859,7 +859,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } #if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216) #define Z7_GETAUXV_AVAILABLE -#else +#elif !defined(__QNXNTO__) // #pragma message("=== is not NEW GLIBC === ") #if defined __has_include #if __has_include () @@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; } #ifdef USE_HWCAP -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) static unsigned long MY_getauxval(int aux) { unsigned long val; diff --git a/3rdparty/lzma/src/LzFind.c b/3rdparty/lzma/src/LzFind.c index 6aba919d02..330bc17293 100644 --- a/3rdparty/lzma/src/LzFind.c +++ b/3rdparty/lzma/src/LzFind.c @@ -598,7 +598,7 @@ void MatchFinder_Init(void *_p) #ifdef MY_CPU_X86_OR_AMD64 #if defined(__clang__) && (__clang_major__ >= 4) \ - || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701) + || defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900) // || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900) #define USE_LZFIND_SATUR_SUB_128 diff --git a/3rdparty/lzma/src/LzmaEnc.c b/3rdparty/lzma/src/LzmaEnc.c index 84a29a5c25..60f1d21da4 100644 --- a/3rdparty/lzma/src/LzmaEnc.c +++ b/3rdparty/lzma/src/LzmaEnc.c @@ -2351,10 +2351,9 @@ static void LzmaEnc_Construct(CLzmaEnc *p) CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) { - void *p; - p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); + CLzmaEncHandle p = (CLzmaEncHandle)ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); if (p) - LzmaEnc_Construct((CLzmaEnc *)p); + LzmaEnc_Construct(p); return p; } diff --git a/3rdparty/lzma/src/Threads.c b/3rdparty/lzma/src/Threads.c index 177d1d9343..08dd58a9d4 100644 --- a/3rdparty/lzma/src/Threads.c +++ b/3rdparty/lzma/src/Threads.c @@ -153,6 +153,17 @@ static void PrintProcess_Info() #endif #endif +/* if we send (stackSize=0) to CreateThread(), it will + use default value PE::SizeOfStackReserve from exe file. + PE::SizeOfStackReserve == 1 MiB in exe file with default linker options. + Windows aligns specified value to the next 64 KB range. */ +static const unsigned k_StackSize_ReserveSize = + #ifdef UNDER_CE + 1 << 17; + #else + 1 << 20; + #endif + WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) { /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ @@ -160,12 +171,15 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) #ifdef USE_THREADS_CreateThread DWORD threadId; - *p = CreateThread(NULL, 0, func, param, 0, &threadId); + *p = CreateThread(NULL, k_StackSize_ReserveSize, func, param, STACK_SIZE_PARAM_IS_A_RESERVATION, &threadId); #else + +#define CALL_beginthreadex(func2, param2, flags, threadIdPtr) \ + ((HANDLE)(_beginthreadex(NULL, k_StackSize_ReserveSize, func2, param2, (flags) | STACK_SIZE_PARAM_IS_A_RESERVATION, threadIdPtr))) unsigned threadId; - *p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId)); + *p = CALL_beginthreadex(func, param, 0, &threadId); #if 0 // 1 : for debug { @@ -223,7 +237,7 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param HANDLE h; WRes wres; unsigned threadId; - h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); + h = CALL_beginthreadex(func, param, CREATE_SUSPENDED, &threadId); *p = h; wres = HandleToWRes(h); if (h) @@ -272,7 +286,7 @@ WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, u HANDLE h; WRes wres; unsigned threadId; - h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId)); + h = CALL_beginthreadex(func, param, CREATE_SUSPENDED, &threadId); *p = h; wres = HandleToWRes(h); if (h) diff --git a/3rdparty/lzma/src/XzDec.c b/3rdparty/lzma/src/XzDec.c index 2dac3247f9..fe6b425aa0 100644 --- a/3rdparty/lzma/src/XzDec.c +++ b/3rdparty/lzma/src/XzDec.c @@ -279,7 +279,7 @@ SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id, decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState)); if (!decoder) return SZ_ERROR_MEM; - decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE); + decoder->buf = (Byte *)ISzAlloc_Alloc(alloc, BRA_BUF_SIZE); if (!decoder->buf) { ISzAlloc_Free(alloc, decoder); @@ -1243,7 +1243,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, UInt32 digest32[XZ_CHECK_SIZE_MAX / 4]; p->state = XZ_STATE_BLOCK_HEADER; p->pos = 0; - if (XzCheck_Final(&p->check, (void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0) + if (XzCheck_Final(&p->check, (Byte *)(void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0) return SZ_ERROR_CRC; if (p->decodeOnlyOneBlock) { @@ -1292,7 +1292,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen, p->state = XZ_STATE_STREAM_INDEX_CRC; p->indexSize += 4; p->pos = 0; - Sha256_Final(&p->sha, (void *)digest32); + Sha256_Final(&p->sha, (Byte *)(void *)digest32); if (memcmp(digest32, p->shaDigest32, SHA256_DIGEST_SIZE) != 0) return SZ_ERROR_CRC; } diff --git a/3rdparty/vixl/CMakeLists.txt b/3rdparty/vixl/CMakeLists.txt index 26325b9614..0304d91bf9 100644 --- a/3rdparty/vixl/CMakeLists.txt +++ b/3rdparty/vixl/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(vixl include/vixl/aarch64/decoder-aarch64.h include/vixl/aarch64/decoder-constants-aarch64.h include/vixl/aarch64/decoder-visitor-map-aarch64.h + include/vixl/aarch64/debugger-aarch64.h include/vixl/aarch64/disasm-aarch64.h include/vixl/aarch64/instructions-aarch64.h include/vixl/aarch64/macro-assembler-aarch64.h @@ -31,6 +32,7 @@ add_library(vixl src/aarch64/cpu-aarch64.cc src/aarch64/cpu-features-auditor-aarch64.cc src/aarch64/decoder-aarch64.cc + src/aarch64/debugger-aarch64.cc src/aarch64/disasm-aarch64.cc src/aarch64/instructions-aarch64.cc src/aarch64/logic-aarch64.cc @@ -39,6 +41,7 @@ add_library(vixl src/aarch64/operands-aarch64.cc src/aarch64/pointer-auth-aarch64.cc src/aarch64/registers-aarch64.cc + src/aarch64/simulator-aarch64.cc src/code-buffer-vixl.cc src/compiler-intrinsics-vixl.cc src/cpu-features.cc diff --git a/3rdparty/vixl/README.md b/3rdparty/vixl/README.md index acf226051b..ef7ad706d0 100644 --- a/3rdparty/vixl/README.md +++ b/3rdparty/vixl/README.md @@ -1,14 +1,16 @@ -VIXL: Armv8 Runtime Code Generation Library, 3.0.0 -================================================== +VIXL: Arm Runtime Code Generation Library +========================================= Contents: - * Overview - * Licence - * Requirements - * Known limitations - * Usage - + * [Overview](#overview) + * [Licence](#licence) + * [Requirements](#requirements) + * [Versioning](#versioning) + * [Supported Arm Architecture Features](#supported-arm-architecture-features) + * [Known limitations](#known-limitations) + * [Bug reports](#bug-reports) + * [Usage](#usage) Overview ======== @@ -16,17 +18,16 @@ Overview VIXL contains three components. 1. Programmatic **assemblers** to generate A64, A32 or T32 code at runtime. The - assemblers abstract some of the constraints of each ISA; for example, most + assemblers abstract some of the constraints of each ISA; for example, some instructions support any immediate. 2. **Disassemblers** that can print any instruction emitted by the assemblers. - 3. A **simulator** that can simulate any instruction emitted by the A64 + 3. An **A64 simulator** that can simulate any instruction emitted by the A64 assembler. The simulator allows generated code to be run on another architecture without the need for a full ISA model. -The VIXL git repository can be found [on 'https://git.linaro.org'][vixl]. +The VIXL git repository can be found [on GitLab][vixl]. -Changes from previous versions of VIXL can be found in the -[Changelog](doc/changelog.md). + Build status: [![Build Status](https://gitlab.arm.com/runtimes/vixl/badges/main/pipeline.svg)](https://gitlab.arm.com/runtimes/vixl/-/pipelines) Licence @@ -35,32 +36,78 @@ Licence This software is covered by the licence described in the [LICENCE](LICENCE) file. +Contributions, as pull requests or via other means, are accepted under the terms +of the same [LICENCE](LICENCE). Requirements ============ To build VIXL the following software is required: - 1. Python 2.7 + 1. Python 3.5+ 2. SCons 2.0 - 3. GCC 4.8+ or Clang 3.4+ + 3. GCC 4.8+ or Clang 4.0+ A 64-bit host machine is required, implementing an LP64 data model. VIXL has been tested using GCC on AArch64 Debian, GCC and Clang on amd64 Ubuntu systems. -To run the linter and code formatting stages of the tests, the following -software is also required: +To run the code formatting stages of the tests, the following software is also required: - 1. Git - 2. [Google's `cpplint.py`][cpplint] - 3. clang-format-3.8 + 1. clang-format 11+ + 2. clang-tidy 11+ Refer to the 'Usage' section for details. +Note that in Ubuntu 18.04, clang-tidy-4.0 will only work if the clang-4.0 +package is also installed. -Known Limitations for AArch64 code generation -============================================= +Versioning +========== + +VIXL uses [Semantic Versioning 2.0.0][semver] - see [VERSIONS](VERSIONS.md) for details. + +Supported Arm Architecture Features +=================================== + +| Feature | VIXL CPUFeatures Flag | Notes | +|------------|-------------------------------|---------------------------------| +| BTI | kBTI | Per-page enabling not supported | +| CSSC | kCSSC | | +| DotProd | kDotProduct | | +| FCMA | kFcma | | +| FHM | kFHM | | +| FP16 | kFPHalf, kNEONHalf | | +| FRINTTS | kFrintToFixedSizedInt | | +| FlagM | kFlagM | | +| FlagM2 | kAXFlag | | +| I8MM | kI8MM | | +| JSCVT | kJSCVT | | +| LOR | kLORegions | | +| LRCPC | kRCpc | | +| LRCPC2 | kRCpcImm | | +| LSE | kAtomics | | +| MOPS | kMOPS | | +| MTE | kMTEInstructions, kMTE, kMTE3 | | +| PAuth | kPAuth, kPAuthGeneric | Not ERETAA, ERETAB | +| RAS | kRAS | | +| RDM | kRDM | | +| SVE | kSVE | | +| SVE2 | kSVE2 | | +| SVEBitPerm | kSVEBitPerm | | +| SVEF32MM | kSVEF32MM | | +| SVEF64MM | kSVEF64MM | | +| SVEI8MM | kSVEI8MM | | + +Enable generating code for an architecture feature by combining a flag with +the MacroAssembler's defaults. For example, to generate code for SVE, use +`masm.GetCPUFeatures()->Combine(CPUFeatures::kSVE);`. + +See [the cpu features header file](src/cpu-features.h) for more information. + + +Known Limitations +================= VIXL was developed for JavaScript engines so a number of features from A64 were deemed unnecessary: @@ -79,11 +126,6 @@ builds and mostly works for 32-bit x86 platforms, there are a number of floating-point operations which do not work correctly, and a number of tests fail as a result. -VIXL may not build using Clang 3.7, due to a compiler warning. A workaround is -to disable conversion of warnings to errors, or to delete the offending -`return` statement reported and rebuild. This problem will be fixed in the next -release. - Debug Builds ------------ @@ -125,6 +167,45 @@ Instructions affected by these limitations: `stlxrh`, `stlxr`, `ldaxrb`, `ldaxrh`, `ldaxr`, `stlxp`, `ldaxp`, `stlrb`, `stlrh`, `stlr`, `ldarb`, `ldarh`, `ldar`, `clrex`. +Security Considerations +----------------------- + +VIXL allows callers to generate any code they want. The generated code is +arbitrary, and can therefore call back into any other component in the process. +As with any self-modifying code, vulnerabilities in the client or in VIXL itself +could lead to arbitrary code generation. + +For performance reasons, VIXL's Assembler only performs debug-mode checking of +instruction operands (such as immediate field encodability). This can minimise +code-generation overheads for advanced compilers that already model instructions +accurately, and might consider the Assembler's checks to be redundant. The +Assembler should only be used directly where encodability is independently +checked, and where fine control over all generated code is required. + +The MacroAssembler synthesises multiple-instruction sequences to support _some_ +unencodable operand combinations. The MacroAssembler can provide a useful safety +check in cases where the Assembler's precision is not required; an unexpected +unencodable operand should result in a macro with the correct behaviour, rather +than an invalid instruction. + +In general, the MacroAssembler handles operands which are likely to vary with +user-supplied data, but does not usually handle inputs which are likely to be +easily covered by tests. For example, move-immediate arguments are likely to be +data-dependent, but register types (e.g. `x` vs `w`) are not. + +We recommend that _all_ users use the MacroAssembler, using `ExactAssemblyScope` +to invoke the Assembler when specific instruction sequences are required. This +approach is recommended even in cases where a compiler can model the +instructions precisely, because, subject to the limitations described above, it +offers an additional layer of protection against logic bugs in instruction +selection. + +Bug reports +=========== + +Bug reports may be made in the Issues section of GitLab, or sent to +vixl@arm.com. Please provide any steps required to recreate a bug, along with +build environment and host system information. Usage ===== @@ -137,23 +218,10 @@ with VIXL, in both release and debug mode. It is a useful script for verifying that all of VIXL's dependencies are in place and that VIXL is working as it should. -By default, the `tools/test.py` script runs a linter to check that the source -code conforms with the code style guide, and to detect several common errors -that the compiler may not warn about. This is most useful for VIXL developers. -The linter has the following dependencies: - - 1. Git must be installed, and the VIXL project must be in a valid Git - repository, such as one produced using `git clone`. - 2. `cpplint.py`, [as provided by Google][cpplint], must be available (and - executable) on the `PATH`. - -It is possible to tell `tools/test.py` to skip the linter stage by passing -`--nolint`. This removes the dependency on `cpplint.py` and Git. The `--nolint` -option is implied if the VIXL project is a snapshot (with no `.git` directory). - -Additionally, `tools/test.py` tests code formatting using `clang-format-3.8`. -If you don't have `clang-format-3.8`, disable the test using the -`--noclang-format` option. +By default, `tools/test.py` tests code formatting using `clang-format-4.0`, +and performs static analysis using `clang-tidy-4.0`. If you don't have these +tools, disable the test using `--noclang-format` or `--noclang-tidy`, +respectively. Also note that the tests for the tracing features depend upon external `diff` and `sed` tools. If these tools are not available in `PATH`, these tests will @@ -173,11 +241,11 @@ aarch32_examples` or `scons aarch64_examples` from the root directory, or use -[cpplint]: http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py - "Google's cpplint.py script." +[vixl]: https://gitlab.arm.com/runtimes/vixl + "The VIXL repository on GitLab." -[vixl]: https://git.linaro.org/arm/vixl.git - "The VIXL repository at 'https://git.linaro.org'." +[semver]: https://semver.org/spec/v2.0.0.html + "Semantic Versioning 2.0.0 Specification" [getting-started-aarch32]: doc/aarch32/getting-started-aarch32.md "Introduction to VIXL for AArch32." diff --git a/3rdparty/vixl/include/vixl/aarch64/assembler-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/assembler-aarch64.h index c1e4e6a787..b05b90fcb3 100644 --- a/3rdparty/vixl/include/vixl/aarch64/assembler-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/assembler-aarch64.h @@ -538,12 +538,18 @@ class Assembler : public vixl::internal::AssemblerBase { // Conditional branch to label. void b(Label* label, Condition cond); + // Conditional branch consistent to label. + void bc(Label* label, Condition cond); + // Unconditional branch to PC offset. void b(int64_t imm26); // Conditional branch to PC offset. void b(int64_t imm19, Condition cond); + // Conditional branch consistent to PC offset. + void bc(int64_t imm19, Condition cond); + // Branch with link to label. void bl(Label* label); @@ -2081,6 +2087,9 @@ class Assembler : public vixl::internal::AssemblerBase { // Prefetch from pc + imm19 << 2 (allowing unallocated hints). void prfm(int op, int64_t imm19); + // Yield. + void yield(); + // Move instructions. The default shift of -1 indicates that the move // instruction will calculate an appropriate 16-bit immediate and left shift // that is equal to the 64-bit immediate argument. If an explicit left shift @@ -2450,6 +2459,16 @@ class Assembler : public vixl::internal::AssemblerBase { // FP convert to unsigned integer, round towards +infinity. void fcvtpu(const VRegister& vd, const VRegister& vn); + // Floating-point convert from single-precision to BFloat16 format (scalar). + void bfcvt(const VRegister& vd, const VRegister& vn); + + // Floating-point convert from single-precision to BFloat16 format (vector). + void bfcvtn(const VRegister& vd, const VRegister& vn); + + // Floating-point convert from single-precision to BFloat16 format (second + // part). + void bfcvtn2(const VRegister& vd, const VRegister& vn); + // Convert signed integer or fixed point to FP. void scvtf(const VRegister& fd, const Register& rn, int fbits = 0); @@ -3732,6 +3751,12 @@ class Assembler : public vixl::internal::AssemblerBase { const VRegister& vm, int index); + // SM4 Encode. + void sm4e(const VRegister& vd, const VRegister& vn); + + // SM4 Key. + void sm4ekey(const VRegister& vd, const VRegister& vn, const VRegister& vm); + // Scalable Vector Extensions. // Absolute value (predicated). @@ -3839,6 +3864,12 @@ class Assembler : public vixl::internal::AssemblerBase { const PRegisterWithLaneSize& pn, const PRegisterWithLaneSize& pm); + // Floating-point down convert to BFloat16 format (predicated). + void bfcvt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn); + + // Floating-point down convert and narrow to BFloat16 (top, predicated). + void bfcvtnt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn); + // Break after first true condition. void brka(const PRegisterWithLaneSize& pd, const PRegister& pg, diff --git a/3rdparty/vixl/include/vixl/aarch64/constants-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/constants-aarch64.h index bcfed30d95..279587cf3f 100644 --- a/3rdparty/vixl/include/vixl/aarch64/constants-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/constants-aarch64.h @@ -27,11 +27,6 @@ #ifndef VIXL_AARCH64_CONSTANTS_AARCH64_H_ #define VIXL_AARCH64_CONSTANTS_AARCH64_H_ -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion" -#endif - #include "../globals-vixl.h" namespace vixl { @@ -502,11 +497,12 @@ class SystemRegisterEncoder { // System/special register names. // This information is not encoded as one field but as the concatenation of // multiple fields (Op0, Op1, Crn, Crm, Op2). -enum SystemRegister : uint32_t { +enum SystemRegister { NZCV = SystemRegisterEncoder<3, 3, 4, 2, 0>::value, FPCR = SystemRegisterEncoder<3, 3, 4, 4, 0>::value, RNDR = SystemRegisterEncoder<3, 3, 2, 4, 0>::value, // Random number. - RNDRRS = SystemRegisterEncoder<3, 3, 2, 4, 1>::value // Reseeded random number. + RNDRRS = SystemRegisterEncoder<3, 3, 2, 4, 1>::value, // Reseeded random number. + DCZID_EL0 = SystemRegisterEncoder<3, 3, 0, 0, 7>::value }; template @@ -519,11 +515,11 @@ class CacheOpEncoder { (op2 << SysOp2_offset)) >> SysOp_offset; }; -enum InstructionCacheOp : uint32_t { +enum InstructionCacheOp { IVAU = CacheOpEncoder<3, 7, 5, 1>::value }; -enum DataCacheOp : uint32_t { +enum DataCacheOp { CVAC = CacheOpEncoder<3, 7, 10, 1>::value, CVAU = CacheOpEncoder<3, 7, 11, 1>::value, CVAP = CacheOpEncoder<3, 7, 12, 1>::value, @@ -540,7 +536,7 @@ enum DataCacheOp : uint32_t { CIGDVAC = CacheOpEncoder<3, 7, 14, 5>::value }; -enum GCSOp : uint32_t { +enum GCSOp { GCSPUSHM = CacheOpEncoder<3, 7, 7, 0>::value, GCSPOPM = CacheOpEncoder<3, 7, 7, 1>::value, GCSSS1 = CacheOpEncoder<3, 7, 7, 2>::value, @@ -598,7 +594,7 @@ enum SVEPredicateConstraint { // Generic fields. -enum GenericInstrField : uint32_t { +enum GenericInstrField { SixtyFourBits = 0x80000000, ThirtyTwoBits = 0x00000000, @@ -608,7 +604,7 @@ enum GenericInstrField : uint32_t { FP64 = 0x00400000 }; -enum NEONFormatField : uint32_t { +enum NEONFormatField { NEONFormatFieldMask = 0x40C00000, NEON_Q = 0x40000000, NEON_8B = 0x00000000, @@ -621,7 +617,7 @@ enum NEONFormatField : uint32_t { NEON_2D = 0x00C00000 | NEON_Q }; -enum NEONFPFormatField : uint32_t { +enum NEONFPFormatField { NEONFPFormatFieldMask = 0x40400000, NEON_FP_4H = FP16, NEON_FP_2S = FP32, @@ -630,7 +626,7 @@ enum NEONFPFormatField : uint32_t { NEON_FP_2D = FP64 | NEON_Q }; -enum NEONLSFormatField : uint32_t { +enum NEONLSFormatField { NEONLSFormatFieldMask = 0x40000C00, LS_NEON_8B = 0x00000000, LS_NEON_16B = LS_NEON_8B | NEON_Q, @@ -642,7 +638,7 @@ enum NEONLSFormatField : uint32_t { LS_NEON_2D = LS_NEON_1D | NEON_Q }; -enum NEONScalarFormatField : uint32_t { +enum NEONScalarFormatField { NEONScalarFormatFieldMask = 0x00C00000, NEONScalar = 0x10000000, NEON_B = 0x00000000, @@ -651,7 +647,7 @@ enum NEONScalarFormatField : uint32_t { NEON_D = 0x00C00000 }; -enum SVESizeField : uint32_t { +enum SVESizeField { SVESizeFieldMask = 0x00C00000, SVE_B = 0x00000000, SVE_H = 0x00400000, @@ -660,7 +656,7 @@ enum SVESizeField : uint32_t { }; // PC relative addressing. -enum PCRelAddressingOp : uint32_t { +enum PCRelAddressingOp { PCRelAddressingFixed = 0x10000000, PCRelAddressingFMask = 0x1F000000, PCRelAddressingMask = 0x9F000000, @@ -670,7 +666,7 @@ enum PCRelAddressingOp : uint32_t { // Add/sub (immediate, shifted and extended.) const int kSFOffset = 31; -enum AddSubOp : uint32_t { +enum AddSubOp { AddSubOpMask = 0x60000000, AddSubSetFlagsBit = 0x20000000, ADD = 0x00000000, @@ -685,7 +681,7 @@ enum AddSubOp : uint32_t { V(SUB), \ V(SUBS) -enum AddSubImmediateOp : uint32_t { +enum AddSubImmediateOp { AddSubImmediateFixed = 0x11000000, AddSubImmediateFMask = 0x1F800000, AddSubImmediateMask = 0xFF800000, @@ -696,7 +692,7 @@ enum AddSubImmediateOp : uint32_t { #undef ADD_SUB_IMMEDIATE }; -enum AddSubShiftedOp : uint32_t { +enum AddSubShiftedOp { AddSubShiftedFixed = 0x0B000000, AddSubShiftedFMask = 0x1F200000, AddSubShiftedMask = 0xFF200000, @@ -707,7 +703,7 @@ enum AddSubShiftedOp : uint32_t { #undef ADD_SUB_SHIFTED }; -enum AddSubExtendedOp : uint32_t { +enum AddSubExtendedOp { AddSubExtendedFixed = 0x0B200000, AddSubExtendedFMask = 0x1F200000, AddSubExtendedMask = 0xFFE00000, @@ -719,7 +715,7 @@ enum AddSubExtendedOp : uint32_t { }; // Add/sub with carry. -enum AddSubWithCarryOp : uint32_t { +enum AddSubWithCarryOp { AddSubWithCarryFixed = 0x1A000000, AddSubWithCarryFMask = 0x1FE00000, AddSubWithCarryMask = 0xFFE0FC00, @@ -736,7 +732,7 @@ enum AddSubWithCarryOp : uint32_t { }; // Rotate right into flags. -enum RotateRightIntoFlagsOp : uint32_t { +enum RotateRightIntoFlagsOp { RotateRightIntoFlagsFixed = 0x1A000400, RotateRightIntoFlagsFMask = 0x1FE07C00, RotateRightIntoFlagsMask = 0xFFE07C10, @@ -744,7 +740,7 @@ enum RotateRightIntoFlagsOp : uint32_t { }; // Evaluate into flags. -enum EvaluateIntoFlagsOp : uint32_t { +enum EvaluateIntoFlagsOp { EvaluateIntoFlagsFixed = 0x1A000800, EvaluateIntoFlagsFMask = 0x1FE03C00, EvaluateIntoFlagsMask = 0xFFE07C1F, @@ -754,7 +750,7 @@ enum EvaluateIntoFlagsOp : uint32_t { // Logical (immediate and shifted register). -enum LogicalOp : uint32_t { +enum LogicalOp { LogicalOpMask = 0x60200000, NOT = 0x00200000, AND = 0x00000000, @@ -768,7 +764,7 @@ enum LogicalOp : uint32_t { }; // Logical immediate. -enum LogicalImmediateOp : uint32_t { +enum LogicalImmediateOp { LogicalImmediateFixed = 0x12000000, LogicalImmediateFMask = 0x1F800000, LogicalImmediateMask = 0xFF800000, @@ -783,7 +779,7 @@ enum LogicalImmediateOp : uint32_t { }; // Logical shifted register. -enum LogicalShiftedOp : uint32_t { +enum LogicalShiftedOp { LogicalShiftedFixed = 0x0A000000, LogicalShiftedFMask = 0x1F000000, LogicalShiftedMask = 0xFF200000, @@ -814,7 +810,7 @@ enum LogicalShiftedOp : uint32_t { }; // Move wide immediate. -enum MoveWideImmediateOp : uint32_t { +enum MoveWideImmediateOp { MoveWideImmediateFixed = 0x12800000, MoveWideImmediateFMask = 0x1F800000, MoveWideImmediateMask = 0xFF800000, @@ -831,7 +827,7 @@ enum MoveWideImmediateOp : uint32_t { // Bitfield. const int kBitfieldNOffset = 22; -enum BitfieldOp : uint32_t { +enum BitfieldOp { BitfieldFixed = 0x13000000, BitfieldFMask = 0x1F800000, BitfieldMask = 0xFF800000, @@ -848,7 +844,7 @@ enum BitfieldOp : uint32_t { }; // Extract. -enum ExtractOp : uint32_t { +enum ExtractOp { ExtractFixed = 0x13800000, ExtractFMask = 0x1F800000, ExtractMask = 0xFFA00000, @@ -858,7 +854,7 @@ enum ExtractOp : uint32_t { }; // Unconditional branch. -enum UnconditionalBranchOp : uint32_t { +enum UnconditionalBranchOp { UnconditionalBranchFixed = 0x14000000, UnconditionalBranchFMask = 0x7C000000, UnconditionalBranchMask = 0xFC000000, @@ -867,7 +863,7 @@ enum UnconditionalBranchOp : uint32_t { }; // Unconditional branch to register. -enum UnconditionalBranchToRegisterOp : uint32_t { +enum UnconditionalBranchToRegisterOp { UnconditionalBranchToRegisterFixed = 0xD6000000, UnconditionalBranchToRegisterFMask = 0xFE000000, UnconditionalBranchToRegisterMask = 0xFFFFFC00, @@ -888,7 +884,7 @@ enum UnconditionalBranchToRegisterOp : uint32_t { }; // Compare and branch. -enum CompareBranchOp : uint32_t { +enum CompareBranchOp { CompareBranchFixed = 0x34000000, CompareBranchFMask = 0x7E000000, CompareBranchMask = 0xFF000000, @@ -901,7 +897,7 @@ enum CompareBranchOp : uint32_t { }; // Test and branch. -enum TestBranchOp : uint32_t { +enum TestBranchOp { TestBranchFixed = 0x36000000, TestBranchFMask = 0x7E000000, TestBranchMask = 0x7F000000, @@ -910,7 +906,7 @@ enum TestBranchOp : uint32_t { }; // Conditional branch. -enum ConditionalBranchOp : uint32_t { +enum ConditionalBranchOp { ConditionalBranchFixed = 0x54000000, ConditionalBranchFMask = 0xFE000000, ConditionalBranchMask = 0xFF000010, @@ -922,12 +918,12 @@ enum ConditionalBranchOp : uint32_t { // and CR fields to encode parameters. To handle this cleanly, the system // instructions are split into more than one enum. -enum SystemOp : uint32_t { +enum SystemOp { SystemFixed = 0xD5000000, SystemFMask = 0xFFC00000 }; -enum SystemSysRegOp : uint32_t { +enum SystemSysRegOp { SystemSysRegFixed = 0xD5100000, SystemSysRegFMask = 0xFFD00000, SystemSysRegMask = 0xFFF00000, @@ -935,7 +931,7 @@ enum SystemSysRegOp : uint32_t { MSR = SystemSysRegFixed | 0x00000000 }; -enum SystemPStateOp : uint32_t { +enum SystemPStateOp { SystemPStateFixed = 0xD5004000, SystemPStateFMask = 0xFFF8F000, SystemPStateMask = 0xFFFFF0FF, @@ -944,14 +940,14 @@ enum SystemPStateOp : uint32_t { AXFLAG = SystemPStateFixed | 0x0000005F }; -enum SystemHintOp : uint32_t { +enum SystemHintOp { SystemHintFixed = 0xD503201F, SystemHintFMask = 0xFFFFF01F, SystemHintMask = 0xFFFFF01F, HINT = SystemHintFixed | 0x00000000 }; -enum SystemSysOp : uint32_t { +enum SystemSysOp { SystemSysFixed = 0xD5080000, SystemSysFMask = 0xFFF80000, SystemSysMask = 0xFFF80000, @@ -960,7 +956,7 @@ enum SystemSysOp : uint32_t { }; // Exception. -enum ExceptionOp : uint32_t { +enum ExceptionOp { ExceptionFixed = 0xD4000000, ExceptionFMask = 0xFF000000, ExceptionMask = 0xFFE0001F, @@ -974,7 +970,7 @@ enum ExceptionOp : uint32_t { DCPS3 = ExceptionFixed | 0x00A00003 }; -enum MemBarrierOp : uint32_t { +enum MemBarrierOp { MemBarrierFixed = 0xD503309F, MemBarrierFMask = 0xFFFFF09F, MemBarrierMask = 0xFFFFF0FF, @@ -983,14 +979,14 @@ enum MemBarrierOp : uint32_t { ISB = MemBarrierFixed | 0x00000040 }; -enum SystemExclusiveMonitorOp : uint32_t { +enum SystemExclusiveMonitorOp { SystemExclusiveMonitorFixed = 0xD503305F, SystemExclusiveMonitorFMask = 0xFFFFF0FF, SystemExclusiveMonitorMask = 0xFFFFF0FF, CLREX = SystemExclusiveMonitorFixed }; -enum SystemPAuthOp : uint32_t { +enum SystemPAuthOp { SystemPAuthFixed = 0xD503211F, SystemPAuthFMask = 0xFFFFFD1F, SystemPAuthMask = 0xFFFFFFFF, @@ -1013,13 +1009,13 @@ enum SystemPAuthOp : uint32_t { }; // Any load or store. -enum LoadStoreAnyOp : uint32_t { +enum LoadStoreAnyOp { LoadStoreAnyFMask = 0x0a000000, LoadStoreAnyFixed = 0x08000000 }; // Any load pair or store pair. -enum LoadStorePairAnyOp : uint32_t { +enum LoadStorePairAnyOp { LoadStorePairAnyFMask = 0x3a000000, LoadStorePairAnyFixed = 0x28000000 }; @@ -1038,7 +1034,7 @@ enum LoadStorePairAnyOp : uint32_t { V(LDP, q, 0x84400000) // Load/store pair (post, pre and offset.) -enum LoadStorePairOp : uint32_t { +enum LoadStorePairOp { LoadStorePairMask = 0xC4400000, LoadStorePairLBit = 1 << 22, #define LOAD_STORE_PAIR(A, B, C) \ @@ -1047,7 +1043,7 @@ enum LoadStorePairOp : uint32_t { #undef LOAD_STORE_PAIR }; -enum LoadStorePairPostIndexOp : uint32_t { +enum LoadStorePairPostIndexOp { LoadStorePairPostIndexFixed = 0x28800000, LoadStorePairPostIndexFMask = 0x3B800000, LoadStorePairPostIndexMask = 0xFFC00000, @@ -1057,7 +1053,7 @@ enum LoadStorePairPostIndexOp : uint32_t { #undef LOAD_STORE_PAIR_POST_INDEX }; -enum LoadStorePairPreIndexOp : uint32_t { +enum LoadStorePairPreIndexOp { LoadStorePairPreIndexFixed = 0x29800000, LoadStorePairPreIndexFMask = 0x3B800000, LoadStorePairPreIndexMask = 0xFFC00000, @@ -1067,7 +1063,7 @@ enum LoadStorePairPreIndexOp : uint32_t { #undef LOAD_STORE_PAIR_PRE_INDEX }; -enum LoadStorePairOffsetOp : uint32_t { +enum LoadStorePairOffsetOp { LoadStorePairOffsetFixed = 0x29000000, LoadStorePairOffsetFMask = 0x3B800000, LoadStorePairOffsetMask = 0xFFC00000, @@ -1077,7 +1073,7 @@ enum LoadStorePairOffsetOp : uint32_t { #undef LOAD_STORE_PAIR_OFFSET }; -enum LoadStorePairNonTemporalOp : uint32_t { +enum LoadStorePairNonTemporalOp { LoadStorePairNonTemporalFixed = 0x28000000, LoadStorePairNonTemporalFMask = 0x3B800000, LoadStorePairNonTemporalMask = 0xFFC00000, @@ -1095,7 +1091,7 @@ enum LoadStorePairNonTemporalOp : uint32_t { }; // Load with pointer authentication. -enum LoadStorePACOp : uint32_t { +enum LoadStorePACOp { LoadStorePACFixed = 0xF8200400, LoadStorePACFMask = 0xFF200400, LoadStorePACMask = 0xFFA00C00, @@ -1107,7 +1103,7 @@ enum LoadStorePACOp : uint32_t { }; // Load literal. -enum LoadLiteralOp : uint32_t { +enum LoadLiteralOp { LoadLiteralFixed = 0x18000000, LoadLiteralFMask = 0x3B000000, LoadLiteralMask = 0xFF000000, @@ -1146,7 +1142,7 @@ enum LoadLiteralOp : uint32_t { V(LD, R, q, 0x04C00000) // Load/store (post, pre, offset and unsigned.) -enum LoadStoreOp : uint32_t { +enum LoadStoreOp { LoadStoreMask = 0xC4C00000, LoadStoreVMask = 0x04000000, #define LOAD_STORE(A, B, C, D) \ @@ -1157,7 +1153,7 @@ enum LoadStoreOp : uint32_t { }; // Load/store unscaled offset. -enum LoadStoreUnscaledOffsetOp : uint32_t { +enum LoadStoreUnscaledOffsetOp { LoadStoreUnscaledOffsetFixed = 0x38000000, LoadStoreUnscaledOffsetFMask = 0x3B200C00, LoadStoreUnscaledOffsetMask = 0xFFE00C00, @@ -1169,7 +1165,7 @@ enum LoadStoreUnscaledOffsetOp : uint32_t { }; // Load/store post index. -enum LoadStorePostIndex : uint32_t { +enum LoadStorePostIndex { LoadStorePostIndexFixed = 0x38000400, LoadStorePostIndexFMask = 0x3B200C00, LoadStorePostIndexMask = 0xFFE00C00, @@ -1180,7 +1176,7 @@ enum LoadStorePostIndex : uint32_t { }; // Load/store pre index. -enum LoadStorePreIndex : uint32_t { +enum LoadStorePreIndex { LoadStorePreIndexFixed = 0x38000C00, LoadStorePreIndexFMask = 0x3B200C00, LoadStorePreIndexMask = 0xFFE00C00, @@ -1191,7 +1187,7 @@ enum LoadStorePreIndex : uint32_t { }; // Load/store unsigned offset. -enum LoadStoreUnsignedOffset : uint32_t { +enum LoadStoreUnsignedOffset { LoadStoreUnsignedOffsetFixed = 0x39000000, LoadStoreUnsignedOffsetFMask = 0x3B000000, LoadStoreUnsignedOffsetMask = 0xFFC00000, @@ -1203,7 +1199,7 @@ enum LoadStoreUnsignedOffset : uint32_t { }; // Load/store register offset. -enum LoadStoreRegisterOffset : uint32_t { +enum LoadStoreRegisterOffset { LoadStoreRegisterOffsetFixed = 0x38200800, LoadStoreRegisterOffsetFMask = 0x3B200C00, LoadStoreRegisterOffsetMask = 0xFFE00C00, @@ -1214,7 +1210,7 @@ enum LoadStoreRegisterOffset : uint32_t { #undef LOAD_STORE_REGISTER_OFFSET }; -enum LoadStoreExclusive : uint32_t { +enum LoadStoreExclusive { LoadStoreExclusiveFixed = 0x08000000, LoadStoreExclusiveFMask = 0x3F000000, LoadStoreExclusiveMask = 0xFFE08000, @@ -1296,7 +1292,7 @@ enum LoadStoreExclusive : uint32_t { }; // Load/store RCpc unscaled offset. -enum LoadStoreRCpcUnscaledOffsetOp : uint32_t { +enum LoadStoreRCpcUnscaledOffsetOp { LoadStoreRCpcUnscaledOffsetFixed = 0x19000000, LoadStoreRCpcUnscaledOffsetFMask = 0x3F200C00, LoadStoreRCpcUnscaledOffsetMask = 0xFFE00C00, @@ -1326,7 +1322,7 @@ enum LoadStoreRCpcUnscaledOffsetOp : uint32_t { V(LDUMIN, 0x00007000) // Atomic memory. -enum AtomicMemoryOp : uint32_t { +enum AtomicMemoryOp { AtomicMemoryFixed = 0x38200000, AtomicMemoryFMask = 0x3B200C00, AtomicMemoryMask = 0xFFE0FC00, @@ -1377,14 +1373,14 @@ enum AtomicMemoryOp : uint32_t { }; // Conditional compare. -enum ConditionalCompareOp : uint32_t { +enum ConditionalCompareOp { ConditionalCompareMask = 0x60000000, CCMN = 0x20000000, CCMP = 0x60000000 }; // Conditional compare register. -enum ConditionalCompareRegisterOp : uint32_t { +enum ConditionalCompareRegisterOp { ConditionalCompareRegisterFixed = 0x1A400000, ConditionalCompareRegisterFMask = 0x1FE00800, ConditionalCompareRegisterMask = 0xFFE00C10, @@ -1395,7 +1391,7 @@ enum ConditionalCompareRegisterOp : uint32_t { }; // Conditional compare immediate. -enum ConditionalCompareImmediateOp : uint32_t { +enum ConditionalCompareImmediateOp { ConditionalCompareImmediateFixed = 0x1A400800, ConditionalCompareImmediateFMask = 0x1FE00800, ConditionalCompareImmediateMask = 0xFFE00C10, @@ -1406,7 +1402,7 @@ enum ConditionalCompareImmediateOp : uint32_t { }; // Conditional select. -enum ConditionalSelectOp : uint32_t { +enum ConditionalSelectOp { ConditionalSelectFixed = 0x1A800000, ConditionalSelectFMask = 0x1FE00000, ConditionalSelectMask = 0xFFE00C00, @@ -1425,7 +1421,7 @@ enum ConditionalSelectOp : uint32_t { }; // Data processing 1 source. -enum DataProcessing1SourceOp : uint32_t { +enum DataProcessing1SourceOp { DataProcessing1SourceFixed = 0x5AC00000, DataProcessing1SourceFMask = 0x5FE00000, DataProcessing1SourceMask = 0xFFFFFC00, @@ -1468,7 +1464,7 @@ enum DataProcessing1SourceOp : uint32_t { }; // Data processing 2 source. -enum DataProcessing2SourceOp : uint32_t { +enum DataProcessing2SourceOp { DataProcessing2SourceFixed = 0x1AC00000, DataProcessing2SourceFMask = 0x5FE00000, DataProcessing2SourceMask = 0xFFE0FC00, @@ -1502,7 +1498,7 @@ enum DataProcessing2SourceOp : uint32_t { }; // Data processing 3 source. -enum DataProcessing3SourceOp : uint32_t { +enum DataProcessing3SourceOp { DataProcessing3SourceFixed = 0x1B000000, DataProcessing3SourceFMask = 0x1F000000, DataProcessing3SourceMask = 0xFFE08000, @@ -1521,7 +1517,7 @@ enum DataProcessing3SourceOp : uint32_t { }; // Floating point compare. -enum FPCompareOp : uint32_t { +enum FPCompareOp { FPCompareFixed = 0x1E202000, FPCompareFMask = 0x5F203C00, FPCompareMask = 0xFFE0FC1F, @@ -1544,7 +1540,7 @@ enum FPCompareOp : uint32_t { }; // Floating point conditional compare. -enum FPConditionalCompareOp : uint32_t { +enum FPConditionalCompareOp { FPConditionalCompareFixed = 0x1E200400, FPConditionalCompareFMask = 0x5F200C00, FPConditionalCompareMask = 0xFFE00C10, @@ -1559,7 +1555,7 @@ enum FPConditionalCompareOp : uint32_t { }; // Floating point conditional select. -enum FPConditionalSelectOp : uint32_t { +enum FPConditionalSelectOp { FPConditionalSelectFixed = 0x1E200C00, FPConditionalSelectFMask = 0x5F200C00, FPConditionalSelectMask = 0xFFE00C00, @@ -1570,7 +1566,7 @@ enum FPConditionalSelectOp : uint32_t { }; // Floating point immediate. -enum FPImmediateOp : uint32_t { +enum FPImmediateOp { FPImmediateFixed = 0x1E201000, FPImmediateFMask = 0x5F201C00, FPImmediateMask = 0xFFE01C00, @@ -1580,7 +1576,7 @@ enum FPImmediateOp : uint32_t { }; // Floating point data processing 1 source. -enum FPDataProcessing1SourceOp : uint32_t { +enum FPDataProcessing1SourceOp { FPDataProcessing1SourceFixed = 0x1E204000, FPDataProcessing1SourceFMask = 0x5F207C00, FPDataProcessing1SourceMask = 0xFFFFFC00, @@ -1649,7 +1645,7 @@ enum FPDataProcessing1SourceOp : uint32_t { }; // Floating point data processing 2 source. -enum FPDataProcessing2SourceOp : uint32_t { +enum FPDataProcessing2SourceOp { FPDataProcessing2SourceFixed = 0x1E200800, FPDataProcessing2SourceFMask = 0x5F200C00, FPDataProcessing2SourceMask = 0xFFE0FC00, @@ -1692,7 +1688,7 @@ enum FPDataProcessing2SourceOp : uint32_t { }; // Floating point data processing 3 source. -enum FPDataProcessing3SourceOp : uint32_t { +enum FPDataProcessing3SourceOp { FPDataProcessing3SourceFixed = 0x1F000000, FPDataProcessing3SourceFMask = 0x5F000000, FPDataProcessing3SourceMask = 0xFFE08000, @@ -1711,7 +1707,7 @@ enum FPDataProcessing3SourceOp : uint32_t { }; // Conversion between floating point and integer. -enum FPIntegerConvertOp : uint32_t { +enum FPIntegerConvertOp { FPIntegerConvertFixed = 0x1E200000, FPIntegerConvertFMask = 0x5F20FC00, FPIntegerConvertMask = 0xFFFFFC00, @@ -1813,7 +1809,7 @@ enum FPIntegerConvertOp : uint32_t { }; // Conversion between fixed point and floating point. -enum FPFixedPointConvertOp : uint32_t { +enum FPFixedPointConvertOp { FPFixedPointConvertFixed = 0x1E000000, FPFixedPointConvertFMask = 0x5F200000, FPFixedPointConvertMask = 0xFFFF0000, @@ -1848,25 +1844,25 @@ enum FPFixedPointConvertOp : uint32_t { }; // Crypto - two register SHA. -enum Crypto2RegSHAOp : uint32_t { +enum Crypto2RegSHAOp { Crypto2RegSHAFixed = 0x5E280800, Crypto2RegSHAFMask = 0xFF3E0C00 }; // Crypto - three register SHA. -enum Crypto3RegSHAOp : uint32_t { +enum Crypto3RegSHAOp { Crypto3RegSHAFixed = 0x5E000000, Crypto3RegSHAFMask = 0xFF208C00 }; // Crypto - AES. -enum CryptoAESOp : uint32_t { +enum CryptoAESOp { CryptoAESFixed = 0x4E280800, CryptoAESFMask = 0xFF3E0C00 }; // NEON instructions with two register operands. -enum NEON2RegMiscOp : uint32_t { +enum NEON2RegMiscOp { NEON2RegMiscFixed = 0x0E200800, NEON2RegMiscFMask = 0x9F3E0C00, NEON2RegMiscMask = 0xBF3FFC00, @@ -1952,7 +1948,7 @@ enum NEON2RegMiscOp : uint32_t { }; // NEON instructions with two register operands (FP16). -enum NEON2RegMiscFP16Op : uint32_t { +enum NEON2RegMiscFP16Op { NEON2RegMiscFP16Fixed = 0x0E780800, NEON2RegMiscFP16FMask = 0x9F7E0C00, NEON2RegMiscFP16Mask = 0xBFFFFC00, @@ -1988,7 +1984,7 @@ enum NEON2RegMiscFP16Op : uint32_t { }; // NEON instructions with three same-type operands. -enum NEON3SameOp : uint32_t { +enum NEON3SameOp { NEON3SameFixed = 0x0E200400, NEON3SameFMask = 0x9F200400, NEON3SameMask = 0xBF20FC00, @@ -2091,7 +2087,7 @@ enum NEON3SameOp : uint32_t { }; -enum NEON3SameFP16 : uint32_t { +enum NEON3SameFP16 { NEON3SameFP16Fixed = 0x0E400400, NEON3SameFP16FMask = 0x9F60C400, NEON3SameFP16Mask = 0xBFE0FC00, @@ -2123,7 +2119,7 @@ enum NEON3SameFP16 : uint32_t { // 'Extra' NEON instructions with three same-type operands. -enum NEON3SameExtraOp : uint32_t { +enum NEON3SameExtraOp { NEON3SameExtraFixed = 0x0E008400, NEON3SameExtraUBit = 0x20000000, NEON3SameExtraFMask = 0x9E208400, @@ -2146,7 +2142,7 @@ enum NEON3SameExtraOp : uint32_t { }; // NEON instructions with three different-type operands. -enum NEON3DifferentOp : uint32_t { +enum NEON3DifferentOp { NEON3DifferentFixed = 0x0E200000, NEON3DifferentFMask = 0x9F200C00, NEON3DifferentMask = 0xFF20FC00, @@ -2205,7 +2201,7 @@ enum NEON3DifferentOp : uint32_t { }; // NEON instructions operating across vectors. -enum NEONAcrossLanesOp : uint32_t { +enum NEONAcrossLanesOp { NEONAcrossLanesFixed = 0x0E300800, NEONAcrossLanesFMask = 0x9F3E0C00, NEONAcrossLanesMask = 0xBF3FFC00, @@ -2237,7 +2233,7 @@ enum NEONAcrossLanesOp : uint32_t { }; // NEON instructions with indexed element operand. -enum NEONByIndexedElementOp : uint32_t { +enum NEONByIndexedElementOp { NEONByIndexedElementFixed = 0x0F000000, NEONByIndexedElementFMask = 0x9F000400, NEONByIndexedElementMask = 0xBF00F400, @@ -2291,7 +2287,7 @@ enum NEONByIndexedElementOp : uint32_t { }; // NEON register copy. -enum NEONCopyOp : uint32_t { +enum NEONCopyOp { NEONCopyFixed = 0x0E000400, NEONCopyFMask = 0x9FE08400, NEONCopyMask = 0x3FE08400, @@ -2310,14 +2306,14 @@ enum NEONCopyOp : uint32_t { }; // NEON extract. -enum NEONExtractOp : uint32_t { +enum NEONExtractOp { NEONExtractFixed = 0x2E000000, NEONExtractFMask = 0xBF208400, NEONExtractMask = 0xBFE08400, NEON_EXT = NEONExtractFixed | 0x00000000 }; -enum NEONLoadStoreMultiOp : uint32_t { +enum NEONLoadStoreMultiOp { NEONLoadStoreMultiL = 0x00400000, NEONLoadStoreMulti1_1v = 0x00007000, NEONLoadStoreMulti1_2v = 0x0000A000, @@ -2329,7 +2325,7 @@ enum NEONLoadStoreMultiOp : uint32_t { }; // NEON load/store multiple structures. -enum NEONLoadStoreMultiStructOp : uint32_t { +enum NEONLoadStoreMultiStructOp { NEONLoadStoreMultiStructFixed = 0x0C000000, NEONLoadStoreMultiStructFMask = 0xBFBF0000, NEONLoadStoreMultiStructMask = 0xBFFFF000, @@ -2353,7 +2349,7 @@ enum NEONLoadStoreMultiStructOp : uint32_t { }; // NEON load/store multiple structures with post-index addressing. -enum NEONLoadStoreMultiStructPostIndexOp : uint32_t { +enum NEONLoadStoreMultiStructPostIndexOp { NEONLoadStoreMultiStructPostIndexFixed = 0x0C800000, NEONLoadStoreMultiStructPostIndexFMask = 0xBFA00000, NEONLoadStoreMultiStructPostIndexMask = 0xBFE0F000, @@ -2374,7 +2370,7 @@ enum NEONLoadStoreMultiStructPostIndexOp : uint32_t { NEON_ST4_post = NEON_ST4 | NEONLoadStoreMultiStructPostIndex }; -enum NEONLoadStoreSingleOp : uint32_t { +enum NEONLoadStoreSingleOp { NEONLoadStoreSingle1 = 0x00000000, NEONLoadStoreSingle2 = 0x00200000, NEONLoadStoreSingle3 = 0x00002000, @@ -2389,7 +2385,7 @@ enum NEONLoadStoreSingleOp : uint32_t { }; // NEON load/store single structure. -enum NEONLoadStoreSingleStructOp : uint32_t { +enum NEONLoadStoreSingleStructOp { NEONLoadStoreSingleStructFixed = 0x0D000000, NEONLoadStoreSingleStructFMask = 0xBF9F0000, NEONLoadStoreSingleStructMask = 0xBFFFE000, @@ -2454,7 +2450,7 @@ enum NEONLoadStoreSingleStructOp : uint32_t { }; // NEON load/store single structure with post-index addressing. -enum NEONLoadStoreSingleStructPostIndexOp : uint32_t { +enum NEONLoadStoreSingleStructPostIndexOp { NEONLoadStoreSingleStructPostIndexFixed = 0x0D800000, NEONLoadStoreSingleStructPostIndexFMask = 0xBF800000, NEONLoadStoreSingleStructPostIndexMask = 0xBFE0E000, @@ -2501,7 +2497,7 @@ enum NEONLoadStoreSingleStructPostIndexOp : uint32_t { }; // NEON modified immediate. -enum NEONModifiedImmediateOp : uint32_t { +enum NEONModifiedImmediateOp { NEONModifiedImmediateFixed = 0x0F000400, NEONModifiedImmediateFMask = 0x9FF80400, NEONModifiedImmediateOpBit = 0x20000000, @@ -2513,7 +2509,7 @@ enum NEONModifiedImmediateOp : uint32_t { }; // NEON shift immediate. -enum NEONShiftImmediateOp : uint32_t { +enum NEONShiftImmediateOp { NEONShiftImmediateFixed = 0x0F000400, NEONShiftImmediateFMask = 0x9F800400, NEONShiftImmediateMask = 0xBF80FC00, @@ -2549,7 +2545,7 @@ enum NEONShiftImmediateOp : uint32_t { }; // NEON table. -enum NEONTableOp : uint32_t { +enum NEONTableOp { NEONTableFixed = 0x0E000000, NEONTableFMask = 0xBF208C00, NEONTableExt = 0x00001000, @@ -2565,7 +2561,7 @@ enum NEONTableOp : uint32_t { }; // NEON perm. -enum NEONPermOp : uint32_t { +enum NEONPermOp { NEONPermFixed = 0x0E000800, NEONPermFMask = 0xBF208C00, NEONPermMask = 0x3F20FC00, @@ -2578,7 +2574,7 @@ enum NEONPermOp : uint32_t { }; // NEON scalar instructions with two register operands. -enum NEONScalar2RegMiscOp : uint32_t { +enum NEONScalar2RegMiscOp { NEONScalar2RegMiscFixed = 0x5E200800, NEONScalar2RegMiscFMask = 0xDF3E0C00, NEONScalar2RegMiscMask = NEON_Q | NEONScalar | NEON2RegMiscMask, @@ -2625,7 +2621,7 @@ enum NEONScalar2RegMiscOp : uint32_t { }; // NEON instructions with two register operands (FP16). -enum NEONScalar2RegMiscFP16Op : uint32_t { +enum NEONScalar2RegMiscFP16Op { NEONScalar2RegMiscFP16Fixed = 0x5E780800, NEONScalar2RegMiscFP16FMask = 0xDF7E0C00, NEONScalar2RegMiscFP16Mask = 0xFFFFFC00, @@ -2652,7 +2648,7 @@ enum NEONScalar2RegMiscFP16Op : uint32_t { }; // NEON scalar instructions with three same-type operands. -enum NEONScalar3SameOp : uint32_t { +enum NEONScalar3SameOp { NEONScalar3SameFixed = 0x5E200400, NEONScalar3SameFMask = 0xDF200400, NEONScalar3SameMask = 0xFF20FC00, @@ -2695,7 +2691,7 @@ enum NEONScalar3SameOp : uint32_t { }; // NEON scalar FP16 instructions with three same-type operands. -enum NEONScalar3SameFP16Op : uint32_t { +enum NEONScalar3SameFP16Op { NEONScalar3SameFP16Fixed = 0x5E400400, NEONScalar3SameFP16FMask = 0xDF60C400, NEONScalar3SameFP16Mask = 0xFFE0FC00, @@ -2711,7 +2707,7 @@ enum NEONScalar3SameFP16Op : uint32_t { }; // 'Extra' NEON scalar instructions with three same-type operands. -enum NEONScalar3SameExtraOp : uint32_t { +enum NEONScalar3SameExtraOp { NEONScalar3SameExtraFixed = 0x5E008400, NEONScalar3SameExtraFMask = 0xDF208400, NEONScalar3SameExtraMask = 0xFF20FC00, @@ -2720,7 +2716,7 @@ enum NEONScalar3SameExtraOp : uint32_t { }; // NEON scalar instructions with three different-type operands. -enum NEONScalar3DiffOp : uint32_t { +enum NEONScalar3DiffOp { NEONScalar3DiffFixed = 0x5E200000, NEONScalar3DiffFMask = 0xDF200C00, NEONScalar3DiffMask = NEON_Q | NEONScalar | NEON3DifferentMask, @@ -2730,7 +2726,7 @@ enum NEONScalar3DiffOp : uint32_t { }; // NEON scalar instructions with indexed element operand. -enum NEONScalarByIndexedElementOp : uint32_t { +enum NEONScalarByIndexedElementOp { NEONScalarByIndexedElementFixed = 0x5F000000, NEONScalarByIndexedElementFMask = 0xDF000400, NEONScalarByIndexedElementMask = 0xFF00F400, @@ -2761,7 +2757,7 @@ enum NEONScalarByIndexedElementOp : uint32_t { }; // NEON scalar register copy. -enum NEONScalarCopyOp : uint32_t { +enum NEONScalarCopyOp { NEONScalarCopyFixed = 0x5E000400, NEONScalarCopyFMask = 0xDFE08400, NEONScalarCopyMask = 0xFFE0FC00, @@ -2769,7 +2765,7 @@ enum NEONScalarCopyOp : uint32_t { }; // NEON scalar pairwise instructions. -enum NEONScalarPairwiseOp : uint32_t { +enum NEONScalarPairwiseOp { NEONScalarPairwiseFixed = 0x5E300800, NEONScalarPairwiseFMask = 0xDF3E0C00, NEONScalarPairwiseMask = 0xFFB1F800, @@ -2787,7 +2783,7 @@ enum NEONScalarPairwiseOp : uint32_t { }; // NEON scalar shift immediate. -enum NEONScalarShiftImmediateOp : uint32_t { +enum NEONScalarShiftImmediateOp { NEONScalarShiftImmediateFixed = 0x5F000400, NEONScalarShiftImmediateFMask = 0xDF800400, NEONScalarShiftImmediateMask = 0xFF80FC00, @@ -2817,7 +2813,7 @@ enum NEONScalarShiftImmediateOp : uint32_t { NEON_FCVTZU_imm_scalar = NEON_Q | NEONScalar | NEON_FCVTZU_imm }; -enum SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsOp : uint32_t { +enum SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsOp { SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFixed = 0x84A00000, SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFMask = 0xFFA08000, SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask = 0xFFA0E000, @@ -2827,7 +2823,7 @@ enum SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsOp : uint32_t { LDFF1H_z_p_bz_s_x32_scaled = SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFixed | 0x00006000 }; -enum SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsOp : uint32_t { +enum SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsOp { SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFixed = 0x85200000, SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFMask = 0xFFA08000, SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask = 0xFFA0E000, @@ -2835,7 +2831,7 @@ enum SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsOp : uint32_t { LDFF1W_z_p_bz_s_x32_scaled = SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFixed | 0x00006000 }; -enum SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsOp : uint32_t { +enum SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsOp { SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFixed = 0x84000000, SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFMask = 0xFE208000, SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask = 0xFFA0E000, @@ -2851,7 +2847,7 @@ enum SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsOp : uint32_t { LDFF1W_z_p_bz_s_x32_unscaled = SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFixed | 0x01006000 }; -enum SVE32BitGatherLoad_VectorPlusImmOp : uint32_t { +enum SVE32BitGatherLoad_VectorPlusImmOp { SVE32BitGatherLoad_VectorPlusImmFixed = 0x84208000, SVE32BitGatherLoad_VectorPlusImmFMask = 0xFE608000, SVE32BitGatherLoad_VectorPlusImmMask = 0xFFE0E000, @@ -2867,7 +2863,7 @@ enum SVE32BitGatherLoad_VectorPlusImmOp : uint32_t { LDFF1W_z_p_ai_s = SVE32BitGatherLoad_VectorPlusImmFixed | 0x01006000 }; -enum SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsOp : uint32_t { +enum SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsOp { SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsFixed = 0x84200000, SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsFMask = 0xFFA08010, SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask = 0xFFA0E010, @@ -2877,7 +2873,7 @@ enum SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsOp : uint32_t { PRFD_i_p_bz_s_x32_scaled = SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsFixed | 0x00006000 }; -enum SVE32BitGatherPrefetch_VectorPlusImmOp : uint32_t { +enum SVE32BitGatherPrefetch_VectorPlusImmOp { SVE32BitGatherPrefetch_VectorPlusImmFixed = 0x8400E000, SVE32BitGatherPrefetch_VectorPlusImmFMask = 0xFE60E010, SVE32BitGatherPrefetch_VectorPlusImmMask = 0xFFE0E010, @@ -2887,7 +2883,7 @@ enum SVE32BitGatherPrefetch_VectorPlusImmOp : uint32_t { PRFD_i_p_ai_s = SVE32BitGatherPrefetch_VectorPlusImmFixed | 0x01800000 }; -enum SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsOp : uint32_t { +enum SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsOp { SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed = 0xE4608000, SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFMask = 0xFE60A000, SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask = 0xFFE0A000, @@ -2895,7 +2891,7 @@ enum SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsOp : uint32_t { ST1W_z_p_bz_s_x32_scaled = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed | 0x01000000 }; -enum SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsOp : uint32_t { +enum SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsOp { SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFixed = 0xE4408000, SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFMask = 0xFE60A000, SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask = 0xFFE0A000, @@ -2904,7 +2900,7 @@ enum SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsOp : uint32_t { ST1W_z_p_bz_s_x32_unscaled = SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFixed | 0x01000000 }; -enum SVE32BitScatterStore_VectorPlusImmOp : uint32_t { +enum SVE32BitScatterStore_VectorPlusImmOp { SVE32BitScatterStore_VectorPlusImmFixed = 0xE460A000, SVE32BitScatterStore_VectorPlusImmFMask = 0xFE60E000, SVE32BitScatterStore_VectorPlusImmMask = 0xFFE0E000, @@ -2913,7 +2909,7 @@ enum SVE32BitScatterStore_VectorPlusImmOp : uint32_t { ST1W_z_p_ai_s = SVE32BitScatterStore_VectorPlusImmFixed | 0x01000000 }; -enum SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsOp : uint32_t { +enum SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsOp { SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFixed = 0xC4200000, SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFMask = 0xFE208000, SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask = 0xFFA0E000, @@ -2929,7 +2925,7 @@ enum SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsOp : uint32_t { LDFF1D_z_p_bz_d_x32_scaled = SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFixed | 0x01806000 }; -enum SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsOp : uint32_t { +enum SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsOp { SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFixed = 0xC4608000, SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFMask = 0xFE608000, SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask = 0xFFE0E000, @@ -2945,7 +2941,7 @@ enum SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsOp : uint32_t { LDFF1D_z_p_bz_d_64_scaled = SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFixed | 0x01806000 }; -enum SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsOp : uint32_t { +enum SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsOp { SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFixed = 0xC4408000, SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFMask = 0xFE608000, SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask = 0xFFE0E000, @@ -2965,7 +2961,7 @@ enum SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsOp : uint32_t { LDFF1D_z_p_bz_d_64_unscaled = SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFixed | 0x01806000 }; -enum SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsOp : uint32_t { +enum SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsOp { SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFixed = 0xC4000000, SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFMask = 0xFE208000, SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask = 0xFFA0E000, @@ -2985,7 +2981,7 @@ enum SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsOp : uint32_t { LDFF1D_z_p_bz_d_x32_unscaled = SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFixed | 0x01806000 }; -enum SVE64BitGatherLoad_VectorPlusImmOp : uint32_t { +enum SVE64BitGatherLoad_VectorPlusImmOp { SVE64BitGatherLoad_VectorPlusImmFixed = 0xC4208000, SVE64BitGatherLoad_VectorPlusImmFMask = 0xFE608000, SVE64BitGatherLoad_VectorPlusImmMask = 0xFFE0E000, @@ -3005,7 +3001,7 @@ enum SVE64BitGatherLoad_VectorPlusImmOp : uint32_t { LDFF1D_z_p_ai_d = SVE64BitGatherLoad_VectorPlusImmFixed | 0x01806000 }; -enum SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsOp : uint32_t { +enum SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsOp { SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsFixed = 0xC4608000, SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsFMask = 0xFFE08010, SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask = 0xFFE0E010, @@ -3015,7 +3011,7 @@ enum SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsOp : uint32_t { PRFD_i_p_bz_d_64_scaled = SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsFixed | 0x00006000 }; -enum SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsOp : uint32_t { +enum SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsOp { SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsFixed = 0xC4200000, SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsFMask = 0xFFA08010, SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask = 0xFFA0E010, @@ -3025,7 +3021,7 @@ enum SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsOp : uint32_t { PRFD_i_p_bz_d_x32_scaled = SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsFixed | 0x00006000 }; -enum SVE64BitGatherPrefetch_VectorPlusImmOp : uint32_t { +enum SVE64BitGatherPrefetch_VectorPlusImmOp { SVE64BitGatherPrefetch_VectorPlusImmFixed = 0xC400E000, SVE64BitGatherPrefetch_VectorPlusImmFMask = 0xFE60E010, SVE64BitGatherPrefetch_VectorPlusImmMask = 0xFFE0E010, @@ -3035,7 +3031,7 @@ enum SVE64BitGatherPrefetch_VectorPlusImmOp : uint32_t { PRFD_i_p_ai_d = SVE64BitGatherPrefetch_VectorPlusImmFixed | 0x01800000 }; -enum SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsOp : uint32_t { +enum SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsOp { SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFixed = 0xE420A000, SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFMask = 0xFE60E000, SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask = 0xFFE0E000, @@ -3044,7 +3040,7 @@ enum SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsOp : uint32_t { ST1D_z_p_bz_d_64_scaled = SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFixed | 0x01800000 }; -enum SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsOp : uint32_t { +enum SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsOp { SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFixed = 0xE400A000, SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFMask = 0xFE60E000, SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask = 0xFFE0E000, @@ -3054,7 +3050,7 @@ enum SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsOp : uint32_t { ST1D_z_p_bz_d_64_unscaled = SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFixed | 0x01800000 }; -enum SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsOp : uint32_t { +enum SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsOp { SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFixed = 0xE4208000, SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFMask = 0xFE60A000, SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask = 0xFFE0A000, @@ -3063,7 +3059,7 @@ enum SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsOp : uint32_t { ST1D_z_p_bz_d_x32_scaled = SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFixed | 0x01800000 }; -enum SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsOp : uint32_t { +enum SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsOp { SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFixed = 0xE4008000, SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFMask = 0xFE60A000, SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask = 0xFFE0A000, @@ -3073,7 +3069,7 @@ enum SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsOp : uint32_t { ST1D_z_p_bz_d_x32_unscaled = SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFixed | 0x01800000 }; -enum SVE64BitScatterStore_VectorPlusImmOp : uint32_t { +enum SVE64BitScatterStore_VectorPlusImmOp { SVE64BitScatterStore_VectorPlusImmFixed = 0xE440A000, SVE64BitScatterStore_VectorPlusImmFMask = 0xFE60E000, SVE64BitScatterStore_VectorPlusImmMask = 0xFFE0E000, @@ -3083,7 +3079,7 @@ enum SVE64BitScatterStore_VectorPlusImmOp : uint32_t { ST1D_z_p_ai_d = SVE64BitScatterStore_VectorPlusImmFixed | 0x01800000 }; -enum SVEAddressGenerationOp : uint32_t { +enum SVEAddressGenerationOp { SVEAddressGenerationFixed = 0x0420A000, SVEAddressGenerationFMask = 0xFF20F000, SVEAddressGenerationMask = 0xFFE0F000, @@ -3093,7 +3089,7 @@ enum SVEAddressGenerationOp : uint32_t { ADR_z_az_d_same_scaled = SVEAddressGenerationFixed | 0x00C00000 }; -enum SVEBitwiseLogicalUnpredicatedOp : uint32_t { +enum SVEBitwiseLogicalUnpredicatedOp { SVEBitwiseLogicalUnpredicatedFixed = 0x04202000, SVEBitwiseLogicalUnpredicatedFMask = 0xFF20E000, SVEBitwiseLogicalUnpredicatedMask = 0xFFE0FC00, @@ -3103,7 +3099,7 @@ enum SVEBitwiseLogicalUnpredicatedOp : uint32_t { BIC_z_zz = SVEBitwiseLogicalUnpredicatedFixed | 0x00C01000 }; -enum SVEBitwiseLogicalWithImm_UnpredicatedOp : uint32_t { +enum SVEBitwiseLogicalWithImm_UnpredicatedOp { SVEBitwiseLogicalWithImm_UnpredicatedFixed = 0x05000000, SVEBitwiseLogicalWithImm_UnpredicatedFMask = 0xFF3C0000, SVEBitwiseLogicalWithImm_UnpredicatedMask = 0xFFFC0000, @@ -3112,7 +3108,7 @@ enum SVEBitwiseLogicalWithImm_UnpredicatedOp : uint32_t { AND_z_zi = SVEBitwiseLogicalWithImm_UnpredicatedFixed | 0x00800000 }; -enum SVEBitwiseLogical_PredicatedOp : uint32_t { +enum SVEBitwiseLogical_PredicatedOp { SVEBitwiseLogical_PredicatedFixed = 0x04180000, SVEBitwiseLogical_PredicatedFMask = 0xFF38E000, SVEBitwiseLogical_PredicatedMask = 0xFF3FE000, @@ -3122,7 +3118,7 @@ enum SVEBitwiseLogical_PredicatedOp : uint32_t { BIC_z_p_zz = SVEBitwiseLogical_PredicatedFixed | 0x00030000 }; -enum SVEBitwiseShiftByImm_PredicatedOp : uint32_t { +enum SVEBitwiseShiftByImm_PredicatedOp { SVEBitwiseShiftByImm_PredicatedFixed = 0x04008000, SVEBitwiseShiftByImm_PredicatedFMask = 0xFF30E000, SVEBitwiseShiftByImm_PredicatedMask = 0xFF3FE000, @@ -3132,7 +3128,7 @@ enum SVEBitwiseShiftByImm_PredicatedOp : uint32_t { ASRD_z_p_zi = SVEBitwiseShiftByImm_PredicatedFixed | 0x00040000 }; -enum SVEBitwiseShiftByVector_PredicatedOp : uint32_t { +enum SVEBitwiseShiftByVector_PredicatedOp { SVEBitwiseShiftByVector_PredicatedFixed = 0x04108000, SVEBitwiseShiftByVector_PredicatedFMask = 0xFF38E000, SVEBitwiseShiftByVector_PredicatedMask = 0xFF3FE000, @@ -3144,7 +3140,7 @@ enum SVEBitwiseShiftByVector_PredicatedOp : uint32_t { LSLR_z_p_zz = SVEBitwiseShiftByVector_PredicatedFixed | 0x00070000 }; -enum SVEBitwiseShiftByWideElements_PredicatedOp : uint32_t { +enum SVEBitwiseShiftByWideElements_PredicatedOp { SVEBitwiseShiftByWideElements_PredicatedFixed = 0x04188000, SVEBitwiseShiftByWideElements_PredicatedFMask = 0xFF38E000, SVEBitwiseShiftByWideElements_PredicatedMask = 0xFF3FE000, @@ -3153,7 +3149,7 @@ enum SVEBitwiseShiftByWideElements_PredicatedOp : uint32_t { LSL_z_p_zw = SVEBitwiseShiftByWideElements_PredicatedFixed | 0x00030000 }; -enum SVEBitwiseShiftUnpredicatedOp : uint32_t { +enum SVEBitwiseShiftUnpredicatedOp { SVEBitwiseShiftUnpredicatedFixed = 0x04208000, SVEBitwiseShiftUnpredicatedFMask = 0xFF20E000, SVEBitwiseShiftUnpredicatedMask = 0xFF20FC00, @@ -3165,49 +3161,49 @@ enum SVEBitwiseShiftUnpredicatedOp : uint32_t { LSL_z_zi = SVEBitwiseShiftUnpredicatedFixed | 0x00001C00 }; -enum SVEBroadcastBitmaskImmOp : uint32_t { +enum SVEBroadcastBitmaskImmOp { SVEBroadcastBitmaskImmFixed = 0x05C00000, SVEBroadcastBitmaskImmFMask = 0xFFFC0000, SVEBroadcastBitmaskImmMask = 0xFFFC0000, DUPM_z_i = SVEBroadcastBitmaskImmFixed }; -enum SVEBroadcastFPImm_UnpredicatedOp : uint32_t { +enum SVEBroadcastFPImm_UnpredicatedOp { SVEBroadcastFPImm_UnpredicatedFixed = 0x2539C000, SVEBroadcastFPImm_UnpredicatedFMask = 0xFF39C000, SVEBroadcastFPImm_UnpredicatedMask = 0xFF3FE000, FDUP_z_i = SVEBroadcastFPImm_UnpredicatedFixed }; -enum SVEBroadcastGeneralRegisterOp : uint32_t { +enum SVEBroadcastGeneralRegisterOp { SVEBroadcastGeneralRegisterFixed = 0x05203800, SVEBroadcastGeneralRegisterFMask = 0xFF3FFC00, SVEBroadcastGeneralRegisterMask = 0xFF3FFC00, DUP_z_r = SVEBroadcastGeneralRegisterFixed }; -enum SVEBroadcastIndexElementOp : uint32_t { +enum SVEBroadcastIndexElementOp { SVEBroadcastIndexElementFixed = 0x05202000, SVEBroadcastIndexElementFMask = 0xFF20FC00, SVEBroadcastIndexElementMask = 0xFF20FC00, DUP_z_zi = SVEBroadcastIndexElementFixed }; -enum SVEBroadcastIntImm_UnpredicatedOp : uint32_t { +enum SVEBroadcastIntImm_UnpredicatedOp { SVEBroadcastIntImm_UnpredicatedFixed = 0x2538C000, SVEBroadcastIntImm_UnpredicatedFMask = 0xFF39C000, SVEBroadcastIntImm_UnpredicatedMask = 0xFF3FC000, DUP_z_i = SVEBroadcastIntImm_UnpredicatedFixed }; -enum SVECompressActiveElementsOp : uint32_t { +enum SVECompressActiveElementsOp { SVECompressActiveElementsFixed = 0x05A18000, SVECompressActiveElementsFMask = 0xFFBFE000, SVECompressActiveElementsMask = 0xFFBFE000, COMPACT_z_p_z = SVECompressActiveElementsFixed }; -enum SVEConditionallyBroadcastElementToVectorOp : uint32_t { +enum SVEConditionallyBroadcastElementToVectorOp { SVEConditionallyBroadcastElementToVectorFixed = 0x05288000, SVEConditionallyBroadcastElementToVectorFMask = 0xFF3EE000, SVEConditionallyBroadcastElementToVectorMask = 0xFF3FE000, @@ -3215,7 +3211,7 @@ enum SVEConditionallyBroadcastElementToVectorOp : uint32_t { CLASTB_z_p_zz = SVEConditionallyBroadcastElementToVectorFixed | 0x00010000 }; -enum SVEConditionallyExtractElementToGeneralRegisterOp : uint32_t { +enum SVEConditionallyExtractElementToGeneralRegisterOp { SVEConditionallyExtractElementToGeneralRegisterFixed = 0x0530A000, SVEConditionallyExtractElementToGeneralRegisterFMask = 0xFF3EE000, SVEConditionallyExtractElementToGeneralRegisterMask = 0xFF3FE000, @@ -3223,7 +3219,7 @@ enum SVEConditionallyExtractElementToGeneralRegisterOp : uint32_t { CLASTB_r_p_z = SVEConditionallyExtractElementToGeneralRegisterFixed | 0x00010000 }; -enum SVEConditionallyExtractElementToSIMDFPScalarOp : uint32_t { +enum SVEConditionallyExtractElementToSIMDFPScalarOp { SVEConditionallyExtractElementToSIMDFPScalarFixed = 0x052A8000, SVEConditionallyExtractElementToSIMDFPScalarFMask = 0xFF3EE000, SVEConditionallyExtractElementToSIMDFPScalarMask = 0xFF3FE000, @@ -3231,7 +3227,7 @@ enum SVEConditionallyExtractElementToSIMDFPScalarOp : uint32_t { CLASTB_v_p_z = SVEConditionallyExtractElementToSIMDFPScalarFixed | 0x00010000 }; -enum SVEConditionallyTerminateScalarsOp : uint32_t { +enum SVEConditionallyTerminateScalarsOp { SVEConditionallyTerminateScalarsFixed = 0x25202000, SVEConditionallyTerminateScalarsFMask = 0xFF20FC0F, SVEConditionallyTerminateScalarsMask = 0xFFA0FC1F, @@ -3239,14 +3235,14 @@ enum SVEConditionallyTerminateScalarsOp : uint32_t { CTERMNE_rr = SVEConditionallyTerminateScalarsFixed | 0x00800010 }; -enum SVEConstructivePrefix_UnpredicatedOp : uint32_t { +enum SVEConstructivePrefix_UnpredicatedOp { SVEConstructivePrefix_UnpredicatedFixed = 0x0420BC00, SVEConstructivePrefix_UnpredicatedFMask = 0xFF20FC00, SVEConstructivePrefix_UnpredicatedMask = 0xFFFFFC00, MOVPRFX_z_z = SVEConstructivePrefix_UnpredicatedFixed }; -enum SVEContiguousFirstFaultLoad_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousFirstFaultLoad_ScalarPlusScalarOp { SVEContiguousFirstFaultLoad_ScalarPlusScalarFixed = 0xA4006000, SVEContiguousFirstFaultLoad_ScalarPlusScalarFMask = 0xFE00E000, SVEContiguousFirstFaultLoad_ScalarPlusScalarMask = 0xFFE0E000, @@ -3268,7 +3264,7 @@ enum SVEContiguousFirstFaultLoad_ScalarPlusScalarOp : uint32_t { LDFF1D_z_p_br_u64 = SVEContiguousFirstFaultLoad_ScalarPlusScalarFixed | 0x01E00000 }; -enum SVEContiguousLoad_ScalarPlusImmOp : uint32_t { +enum SVEContiguousLoad_ScalarPlusImmOp { SVEContiguousLoad_ScalarPlusImmFixed = 0xA400A000, SVEContiguousLoad_ScalarPlusImmFMask = 0xFE10E000, SVEContiguousLoad_ScalarPlusImmMask = 0xFFF0E000, @@ -3290,7 +3286,7 @@ enum SVEContiguousLoad_ScalarPlusImmOp : uint32_t { LD1D_z_p_bi_u64 = SVEContiguousLoad_ScalarPlusImmFixed | 0x01E00000 }; -enum SVEContiguousLoad_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousLoad_ScalarPlusScalarOp { SVEContiguousLoad_ScalarPlusScalarFixed = 0xA4004000, SVEContiguousLoad_ScalarPlusScalarFMask = 0xFE00E000, SVEContiguousLoad_ScalarPlusScalarMask = 0xFFE0E000, @@ -3312,7 +3308,7 @@ enum SVEContiguousLoad_ScalarPlusScalarOp : uint32_t { LD1D_z_p_br_u64 = SVEContiguousLoad_ScalarPlusScalarFixed | 0x01E00000 }; -enum SVEContiguousNonFaultLoad_ScalarPlusImmOp : uint32_t { +enum SVEContiguousNonFaultLoad_ScalarPlusImmOp { SVEContiguousNonFaultLoad_ScalarPlusImmFixed = 0xA410A000, SVEContiguousNonFaultLoad_ScalarPlusImmFMask = 0xFE10E000, SVEContiguousNonFaultLoad_ScalarPlusImmMask = 0xFFF0E000, @@ -3334,7 +3330,7 @@ enum SVEContiguousNonFaultLoad_ScalarPlusImmOp : uint32_t { LDNF1D_z_p_bi_u64 = SVEContiguousNonFaultLoad_ScalarPlusImmFixed | 0x01E00000 }; -enum SVEContiguousNonTemporalLoad_ScalarPlusImmOp : uint32_t { +enum SVEContiguousNonTemporalLoad_ScalarPlusImmOp { SVEContiguousNonTemporalLoad_ScalarPlusImmFixed = 0xA400E000, SVEContiguousNonTemporalLoad_ScalarPlusImmFMask = 0xFE70E000, SVEContiguousNonTemporalLoad_ScalarPlusImmMask = 0xFFF0E000, @@ -3344,7 +3340,7 @@ enum SVEContiguousNonTemporalLoad_ScalarPlusImmOp : uint32_t { LDNT1D_z_p_bi_contiguous = SVEContiguousNonTemporalLoad_ScalarPlusImmFixed | 0x01800000 }; -enum SVEContiguousNonTemporalLoad_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousNonTemporalLoad_ScalarPlusScalarOp { SVEContiguousNonTemporalLoad_ScalarPlusScalarFixed = 0xA400C000, SVEContiguousNonTemporalLoad_ScalarPlusScalarFMask = 0xFE60E000, SVEContiguousNonTemporalLoad_ScalarPlusScalarMask = 0xFFE0E000, @@ -3354,7 +3350,7 @@ enum SVEContiguousNonTemporalLoad_ScalarPlusScalarOp : uint32_t { LDNT1D_z_p_br_contiguous = SVEContiguousNonTemporalLoad_ScalarPlusScalarFixed | 0x01800000 }; -enum SVEContiguousNonTemporalStore_ScalarPlusImmOp : uint32_t { +enum SVEContiguousNonTemporalStore_ScalarPlusImmOp { SVEContiguousNonTemporalStore_ScalarPlusImmFixed = 0xE410E000, SVEContiguousNonTemporalStore_ScalarPlusImmFMask = 0xFE70E000, SVEContiguousNonTemporalStore_ScalarPlusImmMask = 0xFFF0E000, @@ -3364,7 +3360,7 @@ enum SVEContiguousNonTemporalStore_ScalarPlusImmOp : uint32_t { STNT1D_z_p_bi_contiguous = SVEContiguousNonTemporalStore_ScalarPlusImmFixed | 0x01800000 }; -enum SVEContiguousNonTemporalStore_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousNonTemporalStore_ScalarPlusScalarOp { SVEContiguousNonTemporalStore_ScalarPlusScalarFixed = 0xE4006000, SVEContiguousNonTemporalStore_ScalarPlusScalarFMask = 0xFE60E000, SVEContiguousNonTemporalStore_ScalarPlusScalarMask = 0xFFE0E000, @@ -3374,7 +3370,7 @@ enum SVEContiguousNonTemporalStore_ScalarPlusScalarOp : uint32_t { STNT1D_z_p_br_contiguous = SVEContiguousNonTemporalStore_ScalarPlusScalarFixed | 0x01800000 }; -enum SVEContiguousPrefetch_ScalarPlusImmOp : uint32_t { +enum SVEContiguousPrefetch_ScalarPlusImmOp { SVEContiguousPrefetch_ScalarPlusImmFixed = 0x85C00000, SVEContiguousPrefetch_ScalarPlusImmFMask = 0xFFC08010, SVEContiguousPrefetch_ScalarPlusImmMask = 0xFFC0E010, @@ -3384,7 +3380,7 @@ enum SVEContiguousPrefetch_ScalarPlusImmOp : uint32_t { PRFD_i_p_bi_s = SVEContiguousPrefetch_ScalarPlusImmFixed | 0x00006000 }; -enum SVEContiguousPrefetch_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousPrefetch_ScalarPlusScalarOp { SVEContiguousPrefetch_ScalarPlusScalarFixed = 0x8400C000, SVEContiguousPrefetch_ScalarPlusScalarFMask = 0xFE60E010, SVEContiguousPrefetch_ScalarPlusScalarMask = 0xFFE0E010, @@ -3394,7 +3390,7 @@ enum SVEContiguousPrefetch_ScalarPlusScalarOp : uint32_t { PRFD_i_p_br_s = SVEContiguousPrefetch_ScalarPlusScalarFixed | 0x01800000 }; -enum SVEContiguousStore_ScalarPlusImmOp : uint32_t { +enum SVEContiguousStore_ScalarPlusImmOp { SVEContiguousStore_ScalarPlusImmFixed = 0xE400E000, SVEContiguousStore_ScalarPlusImmFMask = 0xFE10E000, SVEContiguousStore_ScalarPlusImmMask = 0xFF90E000, @@ -3404,7 +3400,7 @@ enum SVEContiguousStore_ScalarPlusImmOp : uint32_t { ST1D_z_p_bi = SVEContiguousStore_ScalarPlusImmFixed | 0x01800000 }; -enum SVEContiguousStore_ScalarPlusScalarOp : uint32_t { +enum SVEContiguousStore_ScalarPlusScalarOp { SVEContiguousStore_ScalarPlusScalarFixed = 0xE4004000, SVEContiguousStore_ScalarPlusScalarFMask = 0xFE00E000, SVEContiguousStore_ScalarPlusScalarMask = 0xFF80E000, @@ -3414,35 +3410,35 @@ enum SVEContiguousStore_ScalarPlusScalarOp : uint32_t { ST1D_z_p_br = SVEContiguousStore_ScalarPlusScalarFixed | 0x01800000 }; -enum SVECopyFPImm_PredicatedOp : uint32_t { +enum SVECopyFPImm_PredicatedOp { SVECopyFPImm_PredicatedFixed = 0x0510C000, SVECopyFPImm_PredicatedFMask = 0xFF30E000, SVECopyFPImm_PredicatedMask = 0xFF30E000, FCPY_z_p_i = SVECopyFPImm_PredicatedFixed }; -enum SVECopyGeneralRegisterToVector_PredicatedOp : uint32_t { +enum SVECopyGeneralRegisterToVector_PredicatedOp { SVECopyGeneralRegisterToVector_PredicatedFixed = 0x0528A000, SVECopyGeneralRegisterToVector_PredicatedFMask = 0xFF3FE000, SVECopyGeneralRegisterToVector_PredicatedMask = 0xFF3FE000, CPY_z_p_r = SVECopyGeneralRegisterToVector_PredicatedFixed }; -enum SVECopyIntImm_PredicatedOp : uint32_t { +enum SVECopyIntImm_PredicatedOp { SVECopyIntImm_PredicatedFixed = 0x05100000, SVECopyIntImm_PredicatedFMask = 0xFF308000, SVECopyIntImm_PredicatedMask = 0xFF308000, CPY_z_p_i = SVECopyIntImm_PredicatedFixed }; -enum SVECopySIMDFPScalarRegisterToVector_PredicatedOp : uint32_t { +enum SVECopySIMDFPScalarRegisterToVector_PredicatedOp { SVECopySIMDFPScalarRegisterToVector_PredicatedFixed = 0x05208000, SVECopySIMDFPScalarRegisterToVector_PredicatedFMask = 0xFF3FE000, SVECopySIMDFPScalarRegisterToVector_PredicatedMask = 0xFF3FE000, CPY_z_p_v = SVECopySIMDFPScalarRegisterToVector_PredicatedFixed }; -enum SVEElementCountOp : uint32_t { +enum SVEElementCountOp { SVEElementCountFixed = 0x0420E000, SVEElementCountFMask = 0xFF30F800, SVEElementCountMask = 0xFFF0FC00, @@ -3452,7 +3448,7 @@ enum SVEElementCountOp : uint32_t { CNTD_r_s = SVEElementCountFixed | 0x00C00000 }; -enum SVEExtractElementToGeneralRegisterOp : uint32_t { +enum SVEExtractElementToGeneralRegisterOp { SVEExtractElementToGeneralRegisterFixed = 0x0520A000, SVEExtractElementToGeneralRegisterFMask = 0xFF3EE000, SVEExtractElementToGeneralRegisterMask = 0xFF3FE000, @@ -3460,7 +3456,7 @@ enum SVEExtractElementToGeneralRegisterOp : uint32_t { LASTB_r_p_z = SVEExtractElementToGeneralRegisterFixed | 0x00010000 }; -enum SVEExtractElementToSIMDFPScalarRegisterOp : uint32_t { +enum SVEExtractElementToSIMDFPScalarRegisterOp { SVEExtractElementToSIMDFPScalarRegisterFixed = 0x05228000, SVEExtractElementToSIMDFPScalarRegisterFMask = 0xFF3EE000, SVEExtractElementToSIMDFPScalarRegisterMask = 0xFF3FE000, @@ -3468,28 +3464,28 @@ enum SVEExtractElementToSIMDFPScalarRegisterOp : uint32_t { LASTB_v_p_z = SVEExtractElementToSIMDFPScalarRegisterFixed | 0x00010000 }; -enum SVEFFRInitialiseOp : uint32_t { +enum SVEFFRInitialiseOp { SVEFFRInitialiseFixed = 0x252C9000, SVEFFRInitialiseFMask = 0xFF3FFFFF, SVEFFRInitialiseMask = 0xFFFFFFFF, SETFFR_f = SVEFFRInitialiseFixed }; -enum SVEFFRWriteFromPredicateOp : uint32_t { +enum SVEFFRWriteFromPredicateOp { SVEFFRWriteFromPredicateFixed = 0x25289000, SVEFFRWriteFromPredicateFMask = 0xFF3FFE1F, SVEFFRWriteFromPredicateMask = 0xFFFFFE1F, WRFFR_f_p = SVEFFRWriteFromPredicateFixed }; -enum SVEFPAccumulatingReductionOp : uint32_t { +enum SVEFPAccumulatingReductionOp { SVEFPAccumulatingReductionFixed = 0x65182000, SVEFPAccumulatingReductionFMask = 0xFF38E000, SVEFPAccumulatingReductionMask = 0xFF3FE000, FADDA_v_p_z = SVEFPAccumulatingReductionFixed }; -enum SVEFPArithmeticUnpredicatedOp : uint32_t { +enum SVEFPArithmeticUnpredicatedOp { SVEFPArithmeticUnpredicatedFixed = 0x65000000, SVEFPArithmeticUnpredicatedFMask = 0xFF20E000, SVEFPArithmeticUnpredicatedMask = 0xFF20FC00, @@ -3501,7 +3497,7 @@ enum SVEFPArithmeticUnpredicatedOp : uint32_t { FRSQRTS_z_zz = SVEFPArithmeticUnpredicatedFixed | 0x00001C00 }; -enum SVEFPArithmeticWithImm_PredicatedOp : uint32_t { +enum SVEFPArithmeticWithImm_PredicatedOp { SVEFPArithmeticWithImm_PredicatedFixed = 0x65188000, SVEFPArithmeticWithImm_PredicatedFMask = 0xFF38E3C0, SVEFPArithmeticWithImm_PredicatedMask = 0xFF3FE3C0, @@ -3515,7 +3511,7 @@ enum SVEFPArithmeticWithImm_PredicatedOp : uint32_t { FMIN_z_p_zs = SVEFPArithmeticWithImm_PredicatedFixed | 0x00070000 }; -enum SVEFPArithmetic_PredicatedOp : uint32_t { +enum SVEFPArithmetic_PredicatedOp { SVEFPArithmetic_PredicatedFixed = 0x65008000, SVEFPArithmetic_PredicatedFMask = 0xFF30E000, SVEFPArithmetic_PredicatedMask = 0xFF3FE000, @@ -3534,7 +3530,7 @@ enum SVEFPArithmetic_PredicatedOp : uint32_t { FDIV_z_p_zz = SVEFPArithmetic_PredicatedFixed | 0x000D0000 }; -enum SVEFPCompareVectorsOp : uint32_t { +enum SVEFPCompareVectorsOp { SVEFPCompareVectorsFixed = 0x65004000, SVEFPCompareVectorsFMask = 0xFF204000, SVEFPCompareVectorsMask = 0xFF20E010, @@ -3547,7 +3543,7 @@ enum SVEFPCompareVectorsOp : uint32_t { FACGT_p_p_zz = SVEFPCompareVectorsFixed | 0x0000A010 }; -enum SVEFPCompareWithZeroOp : uint32_t { +enum SVEFPCompareWithZeroOp { SVEFPCompareWithZeroFixed = 0x65102000, SVEFPCompareWithZeroFMask = 0xFF38E000, SVEFPCompareWithZeroMask = 0xFF3FE010, @@ -3559,21 +3555,21 @@ enum SVEFPCompareWithZeroOp : uint32_t { FCMNE_p_p_z0 = SVEFPCompareWithZeroFixed | 0x00030000 }; -enum SVEFPComplexAdditionOp : uint32_t { +enum SVEFPComplexAdditionOp { SVEFPComplexAdditionFixed = 0x64008000, SVEFPComplexAdditionFMask = 0xFF3EE000, SVEFPComplexAdditionMask = 0xFF3EE000, FCADD_z_p_zz = SVEFPComplexAdditionFixed }; -enum SVEFPComplexMulAddOp : uint32_t { +enum SVEFPComplexMulAddOp { SVEFPComplexMulAddFixed = 0x64000000, SVEFPComplexMulAddFMask = 0xFF208000, SVEFPComplexMulAddMask = 0xFF208000, FCMLA_z_p_zzz = SVEFPComplexMulAddFixed }; -enum SVEFPComplexMulAddIndexOp : uint32_t { +enum SVEFPComplexMulAddIndexOp { SVEFPComplexMulAddIndexFixed = 0x64201000, SVEFPComplexMulAddIndexFMask = 0xFF20F000, SVEFPComplexMulAddIndexMask = 0xFFE0F000, @@ -3581,7 +3577,7 @@ enum SVEFPComplexMulAddIndexOp : uint32_t { FCMLA_z_zzzi_s = SVEFPComplexMulAddIndexFixed | 0x00C00000 }; -enum SVEFPConvertPrecisionOp : uint32_t { +enum SVEFPConvertPrecisionOp { SVEFPConvertPrecisionFixed = 0x6508A000, SVEFPConvertPrecisionFMask = 0xFF3CE000, SVEFPConvertPrecisionMask = 0xFFFFE000, @@ -3593,7 +3589,7 @@ enum SVEFPConvertPrecisionOp : uint32_t { FCVT_z_p_z_s2d = SVEFPConvertPrecisionFixed | 0x00C30000 }; -enum SVEFPConvertToIntOp : uint32_t { +enum SVEFPConvertToIntOp { SVEFPConvertToIntFixed = 0x6518A000, SVEFPConvertToIntFMask = 0xFF38E000, SVEFPConvertToIntMask = 0xFFFFE000, @@ -3613,14 +3609,14 @@ enum SVEFPConvertToIntOp : uint32_t { FCVTZU_z_p_z_d2x = SVEFPConvertToIntFixed | 0x00C70000 }; -enum SVEFPExponentialAcceleratorOp : uint32_t { +enum SVEFPExponentialAcceleratorOp { SVEFPExponentialAcceleratorFixed = 0x0420B800, SVEFPExponentialAcceleratorFMask = 0xFF20FC00, SVEFPExponentialAcceleratorMask = 0xFF3FFC00, FEXPA_z_z = SVEFPExponentialAcceleratorFixed }; -enum SVEFPFastReductionOp : uint32_t { +enum SVEFPFastReductionOp { SVEFPFastReductionFixed = 0x65002000, SVEFPFastReductionFMask = 0xFF38E000, SVEFPFastReductionMask = 0xFF3FE000, @@ -3631,7 +3627,7 @@ enum SVEFPFastReductionOp : uint32_t { FMINV_v_p_z = SVEFPFastReductionFixed | 0x00070000 }; -enum SVEFPMulAddOp : uint32_t { +enum SVEFPMulAddOp { SVEFPMulAddFixed = 0x65200000, SVEFPMulAddFMask = 0xFF200000, SVEFPMulAddMask = 0xFF20E000, @@ -3645,7 +3641,7 @@ enum SVEFPMulAddOp : uint32_t { FNMSB_z_p_zzz = SVEFPMulAddFixed | 0x0000E000 }; -enum SVEFPMulAddIndexOp : uint32_t { +enum SVEFPMulAddIndexOp { SVEFPMulAddIndexFixed = 0x64200000, SVEFPMulAddIndexFMask = 0xFF20F800, SVEFPMulAddIndexMask = 0xFFE0FC00, @@ -3659,7 +3655,7 @@ enum SVEFPMulAddIndexOp : uint32_t { FMLS_z_zzzi_d = SVEFPMulAddIndexFixed | 0x00C00400 }; -enum SVEFPMulIndexOp : uint32_t { +enum SVEFPMulIndexOp { SVEFPMulIndexFixed = 0x64202000, SVEFPMulIndexFMask = 0xFF20FC00, SVEFPMulIndexMask = 0xFFE0FC00, @@ -3669,7 +3665,7 @@ enum SVEFPMulIndexOp : uint32_t { FMUL_z_zzi_d = SVEFPMulIndexFixed | 0x00C00000 }; -enum SVEFPRoundToIntegralValueOp : uint32_t { +enum SVEFPRoundToIntegralValueOp { SVEFPRoundToIntegralValueFixed = 0x6500A000, SVEFPRoundToIntegralValueFMask = 0xFF38E000, SVEFPRoundToIntegralValueMask = 0xFF3FE000, @@ -3682,21 +3678,21 @@ enum SVEFPRoundToIntegralValueOp : uint32_t { FRINTI_z_p_z = SVEFPRoundToIntegralValueFixed | 0x00070000 }; -enum SVEFPTrigMulAddCoefficientOp : uint32_t { +enum SVEFPTrigMulAddCoefficientOp { SVEFPTrigMulAddCoefficientFixed = 0x65108000, SVEFPTrigMulAddCoefficientFMask = 0xFF38FC00, SVEFPTrigMulAddCoefficientMask = 0xFF38FC00, FTMAD_z_zzi = SVEFPTrigMulAddCoefficientFixed }; -enum SVEFPTrigSelectCoefficientOp : uint32_t { +enum SVEFPTrigSelectCoefficientOp { SVEFPTrigSelectCoefficientFixed = 0x0420B000, SVEFPTrigSelectCoefficientFMask = 0xFF20F800, SVEFPTrigSelectCoefficientMask = 0xFF20FC00, FTSSEL_z_zz = SVEFPTrigSelectCoefficientFixed }; -enum SVEFPUnaryOpOp : uint32_t { +enum SVEFPUnaryOpOp { SVEFPUnaryOpFixed = 0x650CA000, SVEFPUnaryOpFMask = 0xFF3CE000, SVEFPUnaryOpMask = 0xFF3FE000, @@ -3704,7 +3700,7 @@ enum SVEFPUnaryOpOp : uint32_t { FSQRT_z_p_z = SVEFPUnaryOpFixed | 0x00010000 }; -enum SVEFPUnaryOpUnpredicatedOp : uint32_t { +enum SVEFPUnaryOpUnpredicatedOp { SVEFPUnaryOpUnpredicatedFixed = 0x65083000, SVEFPUnaryOpUnpredicatedFMask = 0xFF38F000, SVEFPUnaryOpUnpredicatedMask = 0xFF3FFC00, @@ -3712,7 +3708,7 @@ enum SVEFPUnaryOpUnpredicatedOp : uint32_t { FRSQRTE_z_z = SVEFPUnaryOpUnpredicatedFixed | 0x00070000 }; -enum SVEIncDecByPredicateCountOp : uint32_t { +enum SVEIncDecByPredicateCountOp { SVEIncDecByPredicateCountFixed = 0x25288000, SVEIncDecByPredicateCountFMask = 0xFF38F000, SVEIncDecByPredicateCountMask = 0xFF3FFE00, @@ -3734,7 +3730,7 @@ enum SVEIncDecByPredicateCountOp : uint32_t { DECP_r_p_r = SVEIncDecByPredicateCountFixed | 0x00050800 }; -enum SVEIncDecRegisterByElementCountOp : uint32_t { +enum SVEIncDecRegisterByElementCountOp { SVEIncDecRegisterByElementCountFixed = 0x0430E000, SVEIncDecRegisterByElementCountFMask = 0xFF30F800, SVEIncDecRegisterByElementCountMask = 0xFFF0FC00, @@ -3748,7 +3744,7 @@ enum SVEIncDecRegisterByElementCountOp : uint32_t { DECD_r_rs = SVEIncDecRegisterByElementCountFixed | 0x00C00400 }; -enum SVEIncDecVectorByElementCountOp : uint32_t { +enum SVEIncDecVectorByElementCountOp { SVEIncDecVectorByElementCountFixed = 0x0430C000, SVEIncDecVectorByElementCountFMask = 0xFF30F800, SVEIncDecVectorByElementCountMask = 0xFFF0FC00, @@ -3760,7 +3756,7 @@ enum SVEIncDecVectorByElementCountOp : uint32_t { DECD_z_zs = SVEIncDecVectorByElementCountFixed | 0x00C00400 }; -enum SVEIndexGenerationOp : uint32_t { +enum SVEIndexGenerationOp { SVEIndexGenerationFixed = 0x04204000, SVEIndexGenerationFMask = 0xFF20F000, SVEIndexGenerationMask = 0xFF20FC00, @@ -3770,21 +3766,21 @@ enum SVEIndexGenerationOp : uint32_t { INDEX_z_rr = SVEIndexGenerationFixed | 0x00000C00 }; -enum SVEInsertGeneralRegisterOp : uint32_t { +enum SVEInsertGeneralRegisterOp { SVEInsertGeneralRegisterFixed = 0x05243800, SVEInsertGeneralRegisterFMask = 0xFF3FFC00, SVEInsertGeneralRegisterMask = 0xFF3FFC00, INSR_z_r = SVEInsertGeneralRegisterFixed }; -enum SVEInsertSIMDFPScalarRegisterOp : uint32_t { +enum SVEInsertSIMDFPScalarRegisterOp { SVEInsertSIMDFPScalarRegisterFixed = 0x05343800, SVEInsertSIMDFPScalarRegisterFMask = 0xFF3FFC00, SVEInsertSIMDFPScalarRegisterMask = 0xFF3FFC00, INSR_z_v = SVEInsertSIMDFPScalarRegisterFixed }; -enum SVEIntAddSubtractImm_UnpredicatedOp : uint32_t { +enum SVEIntAddSubtractImm_UnpredicatedOp { SVEIntAddSubtractImm_UnpredicatedFixed = 0x2520C000, SVEIntAddSubtractImm_UnpredicatedFMask = 0xFF38C000, SVEIntAddSubtractImm_UnpredicatedMask = 0xFF3FC000, @@ -3797,7 +3793,7 @@ enum SVEIntAddSubtractImm_UnpredicatedOp : uint32_t { UQSUB_z_zi = SVEIntAddSubtractImm_UnpredicatedFixed | 0x00070000 }; -enum SVEIntAddSubtractVectors_PredicatedOp : uint32_t { +enum SVEIntAddSubtractVectors_PredicatedOp { SVEIntAddSubtractVectors_PredicatedFixed = 0x04000000, SVEIntAddSubtractVectors_PredicatedFMask = 0xFF38E000, SVEIntAddSubtractVectors_PredicatedMask = 0xFF3FE000, @@ -3806,7 +3802,7 @@ enum SVEIntAddSubtractVectors_PredicatedOp : uint32_t { SUBR_z_p_zz = SVEIntAddSubtractVectors_PredicatedFixed | 0x00030000 }; -enum SVEIntArithmeticUnpredicatedOp : uint32_t { +enum SVEIntArithmeticUnpredicatedOp { SVEIntArithmeticUnpredicatedFixed = 0x04200000, SVEIntArithmeticUnpredicatedFMask = 0xFF20E000, SVEIntArithmeticUnpredicatedMask = 0xFF20FC00, @@ -3818,7 +3814,7 @@ enum SVEIntArithmeticUnpredicatedOp : uint32_t { UQSUB_z_zz = SVEIntArithmeticUnpredicatedFixed | 0x00001C00 }; -enum SVEIntCompareScalarCountAndLimitOp : uint32_t { +enum SVEIntCompareScalarCountAndLimitOp { SVEIntCompareScalarCountAndLimitFixed = 0x25200000, SVEIntCompareScalarCountAndLimitFMask = 0xFF20E000, SVEIntCompareScalarCountAndLimitMask = 0xFF20EC10, @@ -3828,7 +3824,7 @@ enum SVEIntCompareScalarCountAndLimitOp : uint32_t { WHILELS_p_p_rr = SVEIntCompareScalarCountAndLimitFixed | 0x00000C10 }; -enum SVEIntCompareSignedImmOp : uint32_t { +enum SVEIntCompareSignedImmOp { SVEIntCompareSignedImmFixed = 0x25000000, SVEIntCompareSignedImmFMask = 0xFF204000, SVEIntCompareSignedImmMask = 0xFF20E010, @@ -3840,7 +3836,7 @@ enum SVEIntCompareSignedImmOp : uint32_t { CMPNE_p_p_zi = SVEIntCompareSignedImmFixed | 0x00008010 }; -enum SVEIntCompareUnsignedImmOp : uint32_t { +enum SVEIntCompareUnsignedImmOp { SVEIntCompareUnsignedImmFixed = 0x24200000, SVEIntCompareUnsignedImmFMask = 0xFF200000, SVEIntCompareUnsignedImmMask = 0xFF202010, @@ -3850,7 +3846,7 @@ enum SVEIntCompareUnsignedImmOp : uint32_t { CMPLS_p_p_zi = SVEIntCompareUnsignedImmFixed | 0x00002010 }; -enum SVEIntCompareVectorsOp : uint32_t { +enum SVEIntCompareVectorsOp { SVEIntCompareVectorsFixed = 0x24000000, SVEIntCompareVectorsFMask = 0xFF200000, SVEIntCompareVectorsMask = 0xFF20E010, @@ -3872,7 +3868,7 @@ enum SVEIntCompareVectorsOp : uint32_t { CMPLS_p_p_zw = SVEIntCompareVectorsFixed | 0x0000E010 }; -enum SVEIntConvertToFPOp : uint32_t { +enum SVEIntConvertToFPOp { SVEIntConvertToFPFixed = 0x6510A000, SVEIntConvertToFPFMask = 0xFF38E000, SVEIntConvertToFPMask = 0xFFFFE000, @@ -3892,7 +3888,7 @@ enum SVEIntConvertToFPOp : uint32_t { UCVTF_z_p_z_x2d = SVEIntConvertToFPFixed | 0x00C70000 }; -enum SVEIntDivideVectors_PredicatedOp : uint32_t { +enum SVEIntDivideVectors_PredicatedOp { SVEIntDivideVectors_PredicatedFixed = 0x04140000, SVEIntDivideVectors_PredicatedFMask = 0xFF3CE000, SVEIntDivideVectors_PredicatedMask = 0xFF3FE000, @@ -3902,7 +3898,7 @@ enum SVEIntDivideVectors_PredicatedOp : uint32_t { UDIVR_z_p_zz = SVEIntDivideVectors_PredicatedFixed | 0x00030000 }; -enum SVEIntMinMaxDifference_PredicatedOp : uint32_t { +enum SVEIntMinMaxDifference_PredicatedOp { SVEIntMinMaxDifference_PredicatedFixed = 0x04080000, SVEIntMinMaxDifference_PredicatedFMask = 0xFF38E000, SVEIntMinMaxDifference_PredicatedMask = 0xFF3FE000, @@ -3914,7 +3910,7 @@ enum SVEIntMinMaxDifference_PredicatedOp : uint32_t { UABD_z_p_zz = SVEIntMinMaxDifference_PredicatedFixed | 0x00050000 }; -enum SVEIntMinMaxImm_UnpredicatedOp : uint32_t { +enum SVEIntMinMaxImm_UnpredicatedOp { SVEIntMinMaxImm_UnpredicatedFixed = 0x2528C000, SVEIntMinMaxImm_UnpredicatedFMask = 0xFF38C000, SVEIntMinMaxImm_UnpredicatedMask = 0xFF3FE000, @@ -3924,7 +3920,7 @@ enum SVEIntMinMaxImm_UnpredicatedOp : uint32_t { UMIN_z_zi = SVEIntMinMaxImm_UnpredicatedFixed | 0x00030000 }; -enum SVEIntMulAddPredicatedOp : uint32_t { +enum SVEIntMulAddPredicatedOp { SVEIntMulAddPredicatedFixed = 0x04004000, SVEIntMulAddPredicatedFMask = 0xFF204000, SVEIntMulAddPredicatedMask = 0xFF20E000, @@ -3934,7 +3930,7 @@ enum SVEIntMulAddPredicatedOp : uint32_t { MSB_z_p_zzz = SVEIntMulAddPredicatedFixed | 0x0000A000 }; -enum SVEIntMulAddUnpredicatedOp : uint32_t { +enum SVEIntMulAddUnpredicatedOp { SVEIntMulAddUnpredicatedFixed = 0x44000000, SVEIntMulAddUnpredicatedFMask = 0xFF208000, SVEIntMulAddUnpredicatedMask = 0xFF20FC00, @@ -3942,14 +3938,14 @@ enum SVEIntMulAddUnpredicatedOp : uint32_t { UDOT_z_zzz = SVEIntMulAddUnpredicatedFixed | 0x00000400 }; -enum SVEIntMulImm_UnpredicatedOp : uint32_t { +enum SVEIntMulImm_UnpredicatedOp { SVEIntMulImm_UnpredicatedFixed = 0x2530C000, SVEIntMulImm_UnpredicatedFMask = 0xFF38C000, SVEIntMulImm_UnpredicatedMask = 0xFF3FE000, MUL_z_zi = SVEIntMulImm_UnpredicatedFixed }; -enum SVEIntMulVectors_PredicatedOp : uint32_t { +enum SVEIntMulVectors_PredicatedOp { SVEIntMulVectors_PredicatedFixed = 0x04100000, SVEIntMulVectors_PredicatedFMask = 0xFF3CE000, SVEIntMulVectors_PredicatedMask = 0xFF3FE000, @@ -3958,14 +3954,14 @@ enum SVEIntMulVectors_PredicatedOp : uint32_t { UMULH_z_p_zz = SVEIntMulVectors_PredicatedFixed | 0x00030000 }; -enum SVEMovprfxOp : uint32_t { +enum SVEMovprfxOp { SVEMovprfxFixed = 0x04002000, SVEMovprfxFMask = 0xFF20E000, SVEMovprfxMask = 0xFF3EE000, MOVPRFX_z_p_z = SVEMovprfxFixed | 0x00100000 }; -enum SVEIntReductionOp : uint32_t { +enum SVEIntReductionOp { SVEIntReductionFixed = 0x04002000, SVEIntReductionFMask = 0xFF20E000, SVEIntReductionMask = 0xFF3FE000, @@ -3977,7 +3973,7 @@ enum SVEIntReductionOp : uint32_t { UMINV_r_p_z = SVEIntReductionFixed | 0x000B0000 }; -enum SVEIntReductionLogicalOp : uint32_t { +enum SVEIntReductionLogicalOp { SVEIntReductionLogicalFixed = 0x04182000, SVEIntReductionLogicalFMask = 0xFF38E000, SVEIntReductionLogicalMask = 0xFF3FE000, @@ -3986,7 +3982,7 @@ enum SVEIntReductionLogicalOp : uint32_t { ANDV_r_p_z = SVEIntReductionLogicalFixed | 0x001A0000 }; -enum SVEIntUnaryArithmeticPredicatedOp : uint32_t { +enum SVEIntUnaryArithmeticPredicatedOp { SVEIntUnaryArithmeticPredicatedFixed = 0x0400A000, SVEIntUnaryArithmeticPredicatedFMask = 0xFF20E000, SVEIntUnaryArithmeticPredicatedMask = 0xFF3FE000, @@ -4007,7 +4003,7 @@ enum SVEIntUnaryArithmeticPredicatedOp : uint32_t { NOT_z_p_z = SVEIntUnaryArithmeticPredicatedFixed | 0x001E0000 }; -enum SVELoadAndBroadcastElementOp : uint32_t { +enum SVELoadAndBroadcastElementOp { SVELoadAndBroadcastElementFixed = 0x84408000, SVELoadAndBroadcastElementFMask = 0xFE408000, SVELoadAndBroadcastElementMask = 0xFFC0E000, @@ -4029,7 +4025,7 @@ enum SVELoadAndBroadcastElementOp : uint32_t { LD1RD_z_p_bi_u64 = SVELoadAndBroadcastElementFixed | 0x01806000 }; -enum SVELoadAndBroadcastQuadword_ScalarPlusImmOp : uint32_t { +enum SVELoadAndBroadcastQuadword_ScalarPlusImmOp { SVELoadAndBroadcastQuadword_ScalarPlusImmFixed = 0xA4002000, SVELoadAndBroadcastQuadword_ScalarPlusImmFMask = 0xFE10E000, SVELoadAndBroadcastQuadword_ScalarPlusImmMask = 0xFFF0E000, @@ -4039,7 +4035,7 @@ enum SVELoadAndBroadcastQuadword_ScalarPlusImmOp : uint32_t { LD1RQD_z_p_bi_u64 = SVELoadAndBroadcastQuadword_ScalarPlusImmFixed | 0x01800000 }; -enum SVELoadAndBroadcastQuadword_ScalarPlusScalarOp : uint32_t { +enum SVELoadAndBroadcastQuadword_ScalarPlusScalarOp { SVELoadAndBroadcastQuadword_ScalarPlusScalarFixed = 0xA4000000, SVELoadAndBroadcastQuadword_ScalarPlusScalarFMask = 0xFE00E000, SVELoadAndBroadcastQuadword_ScalarPlusScalarMask = 0xFFE0E000, @@ -4049,7 +4045,7 @@ enum SVELoadAndBroadcastQuadword_ScalarPlusScalarOp : uint32_t { LD1RQD_z_p_br_contiguous = SVELoadAndBroadcastQuadword_ScalarPlusScalarFixed | 0x01800000 }; -enum SVELoadMultipleStructures_ScalarPlusImmOp : uint32_t { +enum SVELoadMultipleStructures_ScalarPlusImmOp { SVELoadMultipleStructures_ScalarPlusImmFixed = 0xA400E000, SVELoadMultipleStructures_ScalarPlusImmFMask = 0xFE10E000, SVELoadMultipleStructures_ScalarPlusImmMask = 0xFFF0E000, @@ -4067,7 +4063,7 @@ enum SVELoadMultipleStructures_ScalarPlusImmOp : uint32_t { LD4D_z_p_bi_contiguous = SVELoadMultipleStructures_ScalarPlusImmFixed | 0x01E00000 }; -enum SVELoadMultipleStructures_ScalarPlusScalarOp : uint32_t { +enum SVELoadMultipleStructures_ScalarPlusScalarOp { SVELoadMultipleStructures_ScalarPlusScalarFixed = 0xA400C000, SVELoadMultipleStructures_ScalarPlusScalarFMask = 0xFE00E000, SVELoadMultipleStructures_ScalarPlusScalarMask = 0xFFE0E000, @@ -4085,21 +4081,21 @@ enum SVELoadMultipleStructures_ScalarPlusScalarOp : uint32_t { LD4D_z_p_br_contiguous = SVELoadMultipleStructures_ScalarPlusScalarFixed | 0x01E00000 }; -enum SVELoadPredicateRegisterOp : uint32_t { +enum SVELoadPredicateRegisterOp { SVELoadPredicateRegisterFixed = 0x85800000, SVELoadPredicateRegisterFMask = 0xFFC0E010, SVELoadPredicateRegisterMask = 0xFFC0E010, LDR_p_bi = SVELoadPredicateRegisterFixed }; -enum SVELoadVectorRegisterOp : uint32_t { +enum SVELoadVectorRegisterOp { SVELoadVectorRegisterFixed = 0x85804000, SVELoadVectorRegisterFMask = 0xFFC0E000, SVELoadVectorRegisterMask = 0xFFC0E000, LDR_z_bi = SVELoadVectorRegisterFixed }; -enum SVEMulIndexOp : uint32_t { +enum SVEMulIndexOp { SVEMulIndexFixed = 0x44200000, SVEMulIndexFMask = 0xFF200000, SVEMulIndexMask = 0xFFE0FC00, @@ -4109,7 +4105,7 @@ enum SVEMulIndexOp : uint32_t { UDOT_z_zzzi_d = SVEMulIndexFixed | 0x00C00400 }; -enum SVEPartitionBreakConditionOp : uint32_t { +enum SVEPartitionBreakConditionOp { SVEPartitionBreakConditionFixed = 0x25104000, SVEPartitionBreakConditionFMask = 0xFF3FC200, SVEPartitionBreakConditionMask = 0xFFFFC200, @@ -4119,7 +4115,7 @@ enum SVEPartitionBreakConditionOp : uint32_t { BRKBS_p_p_p_z = SVEPartitionBreakConditionFixed | 0x00C00000 }; -enum SVEPermutePredicateElementsOp : uint32_t { +enum SVEPermutePredicateElementsOp { SVEPermutePredicateElementsFixed = 0x05204000, SVEPermutePredicateElementsFMask = 0xFF30E210, SVEPermutePredicateElementsMask = 0xFF30FE10, @@ -4131,14 +4127,14 @@ enum SVEPermutePredicateElementsOp : uint32_t { TRN2_p_pp = SVEPermutePredicateElementsFixed | 0x00001400 }; -enum SVEPermuteVectorExtractOp : uint32_t { +enum SVEPermuteVectorExtractOp { SVEPermuteVectorExtractFixed = 0x05200000, SVEPermuteVectorExtractFMask = 0xFF20E000, SVEPermuteVectorExtractMask = 0xFFE0E000, EXT_z_zi_des = SVEPermuteVectorExtractFixed }; -enum SVEPermuteVectorInterleavingOp : uint32_t { +enum SVEPermuteVectorInterleavingOp { SVEPermuteVectorInterleavingFixed = 0x05206000, SVEPermuteVectorInterleavingFMask = 0xFF20E000, SVEPermuteVectorInterleavingMask = 0xFF20FC00, @@ -4150,21 +4146,21 @@ enum SVEPermuteVectorInterleavingOp : uint32_t { TRN2_z_zz = SVEPermuteVectorInterleavingFixed | 0x00001400 }; -enum SVEPredicateCountOp : uint32_t { +enum SVEPredicateCountOp { SVEPredicateCountFixed = 0x25208000, SVEPredicateCountFMask = 0xFF38C000, SVEPredicateCountMask = 0xFF3FC200, CNTP_r_p_p = SVEPredicateCountFixed }; -enum SVEPredicateFirstActiveOp : uint32_t { +enum SVEPredicateFirstActiveOp { SVEPredicateFirstActiveFixed = 0x2518C000, SVEPredicateFirstActiveFMask = 0xFF3FFE10, SVEPredicateFirstActiveMask = 0xFFFFFE10, PFIRST_p_p_p = SVEPredicateFirstActiveFixed | 0x00400000 }; -enum SVEPredicateInitializeOp : uint32_t { +enum SVEPredicateInitializeOp { SVEPredicateInitializeFixed = 0x2518E000, SVEPredicateInitializeFMask = 0xFF3EFC10, SVEPredicateInitializeMask = 0xFF3FFC10, @@ -4173,7 +4169,7 @@ enum SVEPredicateInitializeOp : uint32_t { PTRUES_p_s = SVEPredicateInitializeFixed | SVEPredicateInitializeSetFlagsBit }; -enum SVEPredicateLogicalOp : uint32_t { +enum SVEPredicateLogicalOp { SVEPredicateLogicalFixed = 0x25004000, SVEPredicateLogicalFMask = 0xFF30C000, SVEPredicateLogicalMask = 0xFFF0C210, @@ -4195,14 +4191,14 @@ enum SVEPredicateLogicalOp : uint32_t { SEL_p_p_pp = SVEPredicateLogicalFixed | 0x00000210 }; -enum SVEPredicateNextActiveOp : uint32_t { +enum SVEPredicateNextActiveOp { SVEPredicateNextActiveFixed = 0x2519C400, SVEPredicateNextActiveFMask = 0xFF3FFE10, SVEPredicateNextActiveMask = 0xFF3FFE10, PNEXT_p_p_p = SVEPredicateNextActiveFixed }; -enum SVEPredicateReadFromFFR_PredicatedOp : uint32_t { +enum SVEPredicateReadFromFFR_PredicatedOp { SVEPredicateReadFromFFR_PredicatedFixed = 0x2518F000, SVEPredicateReadFromFFR_PredicatedFMask = 0xFF3FFE10, SVEPredicateReadFromFFR_PredicatedMask = 0xFFFFFE10, @@ -4210,28 +4206,28 @@ enum SVEPredicateReadFromFFR_PredicatedOp : uint32_t { RDFFRS_p_p_f = SVEPredicateReadFromFFR_PredicatedFixed | 0x00400000 }; -enum SVEPredicateReadFromFFR_UnpredicatedOp : uint32_t { +enum SVEPredicateReadFromFFR_UnpredicatedOp { SVEPredicateReadFromFFR_UnpredicatedFixed = 0x2519F000, SVEPredicateReadFromFFR_UnpredicatedFMask = 0xFF3FFFF0, SVEPredicateReadFromFFR_UnpredicatedMask = 0xFFFFFFF0, RDFFR_p_f = SVEPredicateReadFromFFR_UnpredicatedFixed }; -enum SVEPredicateTestOp : uint32_t { +enum SVEPredicateTestOp { SVEPredicateTestFixed = 0x2510C000, SVEPredicateTestFMask = 0xFF3FC210, SVEPredicateTestMask = 0xFFFFC21F, PTEST_p_p = SVEPredicateTestFixed | 0x00400000 }; -enum SVEPredicateZeroOp : uint32_t { +enum SVEPredicateZeroOp { SVEPredicateZeroFixed = 0x2518E400, SVEPredicateZeroFMask = 0xFF3FFFF0, SVEPredicateZeroMask = 0xFFFFFFF0, PFALSE_p = SVEPredicateZeroFixed }; -enum SVEPropagateBreakOp : uint32_t { +enum SVEPropagateBreakOp { SVEPropagateBreakFixed = 0x2500C000, SVEPropagateBreakFMask = 0xFF30C000, SVEPropagateBreakMask = 0xFFF0C210, @@ -4241,7 +4237,7 @@ enum SVEPropagateBreakOp : uint32_t { BRKPBS_p_p_pp = SVEPropagateBreakFixed | 0x00400010 }; -enum SVEPropagateBreakToNextPartitionOp : uint32_t { +enum SVEPropagateBreakToNextPartitionOp { SVEPropagateBreakToNextPartitionFixed = 0x25184000, SVEPropagateBreakToNextPartitionFMask = 0xFFBFC210, SVEPropagateBreakToNextPartitionMask = 0xFFFFC210, @@ -4249,21 +4245,21 @@ enum SVEPropagateBreakToNextPartitionOp : uint32_t { BRKNS_p_p_pp = SVEPropagateBreakToNextPartitionFixed | 0x00400000 }; -enum SVEReversePredicateElementsOp : uint32_t { +enum SVEReversePredicateElementsOp { SVEReversePredicateElementsFixed = 0x05344000, SVEReversePredicateElementsFMask = 0xFF3FFE10, SVEReversePredicateElementsMask = 0xFF3FFE10, REV_p_p = SVEReversePredicateElementsFixed }; -enum SVEReverseVectorElementsOp : uint32_t { +enum SVEReverseVectorElementsOp { SVEReverseVectorElementsFixed = 0x05383800, SVEReverseVectorElementsFMask = 0xFF3FFC00, SVEReverseVectorElementsMask = 0xFF3FFC00, REV_z_z = SVEReverseVectorElementsFixed }; -enum SVEReverseWithinElementsOp : uint32_t { +enum SVEReverseWithinElementsOp { SVEReverseWithinElementsFixed = 0x05248000, SVEReverseWithinElementsFMask = 0xFF3CE000, SVEReverseWithinElementsMask = 0xFF3FE000, @@ -4273,7 +4269,7 @@ enum SVEReverseWithinElementsOp : uint32_t { RBIT_z_p_z = SVEReverseWithinElementsFixed | 0x00030000 }; -enum SVESaturatingIncDecRegisterByElementCountOp : uint32_t { +enum SVESaturatingIncDecRegisterByElementCountOp { SVESaturatingIncDecRegisterByElementCountFixed = 0x0420F000, SVESaturatingIncDecRegisterByElementCountFMask = 0xFF20F000, SVESaturatingIncDecRegisterByElementCountMask = 0xFFF0FC00, @@ -4311,7 +4307,7 @@ enum SVESaturatingIncDecRegisterByElementCountOp : uint32_t { UQDECD_r_rs_x = SVESaturatingIncDecRegisterByElementCountFixed | 0x00D00C00 }; -enum SVESaturatingIncDecVectorByElementCountOp : uint32_t { +enum SVESaturatingIncDecVectorByElementCountOp { SVESaturatingIncDecVectorByElementCountFixed = 0x0420C000, SVESaturatingIncDecVectorByElementCountFMask = 0xFF30F000, SVESaturatingIncDecVectorByElementCountMask = 0xFFF0FC00, @@ -4329,7 +4325,7 @@ enum SVESaturatingIncDecVectorByElementCountOp : uint32_t { UQDECD_z_zs = SVESaturatingIncDecVectorByElementCountFixed | 0x00C00C00 }; -enum SVEStackFrameAdjustmentOp : uint32_t { +enum SVEStackFrameAdjustmentOp { SVEStackFrameAdjustmentFixed = 0x04205000, SVEStackFrameAdjustmentFMask = 0xFFA0F800, SVEStackFrameAdjustmentMask = 0xFFE0F800, @@ -4337,14 +4333,14 @@ enum SVEStackFrameAdjustmentOp : uint32_t { ADDPL_r_ri = SVEStackFrameAdjustmentFixed | 0x00400000 }; -enum SVEStackFrameSizeOp : uint32_t { +enum SVEStackFrameSizeOp { SVEStackFrameSizeFixed = 0x04BF5000, SVEStackFrameSizeFMask = 0xFFFFF800, SVEStackFrameSizeMask = 0xFFFFF800, RDVL_r_i = SVEStackFrameSizeFixed }; -enum SVEStoreMultipleStructures_ScalarPlusImmOp : uint32_t { +enum SVEStoreMultipleStructures_ScalarPlusImmOp { SVEStoreMultipleStructures_ScalarPlusImmFixed = 0xE410E000, SVEStoreMultipleStructures_ScalarPlusImmFMask = 0xFE10E000, SVEStoreMultipleStructures_ScalarPlusImmMask = 0xFFF0E000, @@ -4362,7 +4358,7 @@ enum SVEStoreMultipleStructures_ScalarPlusImmOp : uint32_t { ST4D_z_p_bi_contiguous = SVEStoreMultipleStructures_ScalarPlusImmFixed | 0x01E00000 }; -enum SVEStoreMultipleStructures_ScalarPlusScalarOp : uint32_t { +enum SVEStoreMultipleStructures_ScalarPlusScalarOp { SVEStoreMultipleStructures_ScalarPlusScalarFixed = 0xE4006000, SVEStoreMultipleStructures_ScalarPlusScalarFMask = 0xFE00E000, SVEStoreMultipleStructures_ScalarPlusScalarMask = 0xFFE0E000, @@ -4380,28 +4376,28 @@ enum SVEStoreMultipleStructures_ScalarPlusScalarOp : uint32_t { ST4D_z_p_br_contiguous = SVEStoreMultipleStructures_ScalarPlusScalarFixed | 0x01E00000 }; -enum SVEStorePredicateRegisterOp : uint32_t { +enum SVEStorePredicateRegisterOp { SVEStorePredicateRegisterFixed = 0xE5800000, SVEStorePredicateRegisterFMask = 0xFFC0E010, SVEStorePredicateRegisterMask = 0xFFC0E010, STR_p_bi = SVEStorePredicateRegisterFixed }; -enum SVEStoreVectorRegisterOp : uint32_t { +enum SVEStoreVectorRegisterOp { SVEStoreVectorRegisterFixed = 0xE5804000, SVEStoreVectorRegisterFMask = 0xFFC0E000, SVEStoreVectorRegisterMask = 0xFFC0E000, STR_z_bi = SVEStoreVectorRegisterFixed }; -enum SVETableLookupOp : uint32_t { +enum SVETableLookupOp { SVETableLookupFixed = 0x05203000, SVETableLookupFMask = 0xFF20FC00, SVETableLookupMask = 0xFF20FC00, TBL_z_zz_1 = SVETableLookupFixed }; -enum SVEUnpackPredicateElementsOp : uint32_t { +enum SVEUnpackPredicateElementsOp { SVEUnpackPredicateElementsFixed = 0x05304000, SVEUnpackPredicateElementsFMask = 0xFFFEFE10, SVEUnpackPredicateElementsMask = 0xFFFFFE10, @@ -4409,7 +4405,7 @@ enum SVEUnpackPredicateElementsOp : uint32_t { PUNPKHI_p_p = SVEUnpackPredicateElementsFixed | 0x00010000 }; -enum SVEUnpackVectorElementsOp : uint32_t { +enum SVEUnpackVectorElementsOp { SVEUnpackVectorElementsFixed = 0x05303800, SVEUnpackVectorElementsFMask = 0xFF3CFC00, SVEUnpackVectorElementsMask = 0xFF3FFC00, @@ -4419,21 +4415,21 @@ enum SVEUnpackVectorElementsOp : uint32_t { UUNPKHI_z_z = SVEUnpackVectorElementsFixed | 0x00030000 }; -enum SVEVectorSelectOp : uint32_t { +enum SVEVectorSelectOp { SVEVectorSelectFixed = 0x0520C000, SVEVectorSelectFMask = 0xFF20C000, SVEVectorSelectMask = 0xFF20C000, SEL_z_p_zz = SVEVectorSelectFixed }; -enum SVEVectorSpliceOp : uint32_t { +enum SVEVectorSpliceOp { SVEVectorSpliceFixed = 0x052C8000, SVEVectorSpliceFMask = 0xFF3FE000, SVEVectorSpliceMask = 0xFF3FE000, SPLICE_z_p_zz_des = SVEVectorSpliceFixed }; -enum ReservedOp : uint32_t { +enum ReservedOp { ReservedFixed = 0x00000000, ReservedFMask = 0x1E000000, ReservedMask = 0xFFFF0000, @@ -4442,12 +4438,12 @@ enum ReservedOp : uint32_t { // Unimplemented and unallocated instructions. These are defined to make fixed // bit assertion easier. -enum UnimplementedOp : uint32_t { +enum UnimplementedOp { UnimplementedFixed = 0x00000000, UnimplementedFMask = 0x00000000 }; -enum UnallocatedOp : uint32_t { +enum UnallocatedOp { UnallocatedFixed = 0x00000000, UnallocatedFMask = 0x00000000 }; diff --git a/3rdparty/vixl/include/vixl/aarch64/cpu-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/cpu-aarch64.h index d5a5f8c82e..a5dd2f497e 100644 --- a/3rdparty/vixl/include/vixl/aarch64/cpu-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/cpu-aarch64.h @@ -173,6 +173,7 @@ class AA64ISAR2 : public IDRegister { static const Field kRPRES; static const Field kMOPS; static const Field kCSSC; + static const Field kHBC; }; class AA64MMFR0 : public IDRegister { diff --git a/3rdparty/vixl/include/vixl/aarch64/cpu-features-auditor-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/cpu-features-auditor-aarch64.h index 7d5ca2f455..ed33c75d18 100644 --- a/3rdparty/vixl/include/vixl/aarch64/cpu-features-auditor-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/cpu-features-auditor-aarch64.h @@ -111,9 +111,10 @@ class CPUFeaturesAuditor : public DecoderVisitor { class RecordInstructionFeaturesScope; #define DECLARE(A) virtual void Visit##A(const Instruction* instr); - VISITOR_LIST(DECLARE) + SIM_AUD_VISITOR_LIST(DECLARE) #undef DECLARE void VisitCryptoSM3(const Instruction* instr); + void VisitCryptoSM4(const Instruction* instr); void LoadStoreHelper(const Instruction* instr); void LoadStorePairHelper(const Instruction* instr); diff --git a/3rdparty/vixl/include/vixl/aarch64/decoder-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/decoder-aarch64.h index 22c66e82a4..3eb42087b2 100644 --- a/3rdparty/vixl/include/vixl/aarch64/decoder-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/decoder-aarch64.h @@ -30,240 +30,244 @@ #include #include #include +#include +#include #include "../globals-vixl.h" #include "instructions-aarch64.h" // List macro containing all visitors needed by the decoder class. -#define VISITOR_LIST_THAT_RETURN(V) \ - V(AddSubExtended) \ - V(AddSubImmediate) \ - V(AddSubShifted) \ - V(AddSubWithCarry) \ - V(AtomicMemory) \ - V(Bitfield) \ - V(CompareBranch) \ - V(ConditionalBranch) \ - V(ConditionalCompareImmediate) \ - V(ConditionalCompareRegister) \ - V(ConditionalSelect) \ - V(Crypto2RegSHA) \ - V(Crypto3RegSHA) \ - V(CryptoAES) \ - V(DataProcessing1Source) \ - V(DataProcessing2Source) \ - V(DataProcessing3Source) \ - V(EvaluateIntoFlags) \ - V(Exception) \ - V(Extract) \ - V(FPCompare) \ - V(FPConditionalCompare) \ - V(FPConditionalSelect) \ - V(FPDataProcessing1Source) \ - V(FPDataProcessing2Source) \ - V(FPDataProcessing3Source) \ - V(FPFixedPointConvert) \ - V(FPImmediate) \ - V(FPIntegerConvert) \ - V(LoadLiteral) \ - V(LoadStoreExclusive) \ - V(LoadStorePAC) \ - V(LoadStorePairNonTemporal) \ - V(LoadStorePairOffset) \ - V(LoadStorePairPostIndex) \ - V(LoadStorePairPreIndex) \ - V(LoadStorePostIndex) \ - V(LoadStorePreIndex) \ - V(LoadStoreRCpcUnscaledOffset) \ - V(LoadStoreRegisterOffset) \ - V(LoadStoreUnscaledOffset) \ - V(LoadStoreUnsignedOffset) \ - V(LogicalImmediate) \ - V(LogicalShifted) \ - V(MoveWideImmediate) \ - V(NEON2RegMisc) \ - V(NEON2RegMiscFP16) \ - V(NEON3Different) \ - V(NEON3Same) \ - V(NEON3SameExtra) \ - V(NEON3SameFP16) \ - V(NEONAcrossLanes) \ - V(NEONByIndexedElement) \ - V(NEONCopy) \ - V(NEONExtract) \ - V(NEONLoadStoreMultiStruct) \ - V(NEONLoadStoreMultiStructPostIndex) \ - V(NEONLoadStoreSingleStruct) \ - V(NEONLoadStoreSingleStructPostIndex) \ - V(NEONModifiedImmediate) \ - V(NEONPerm) \ - V(NEONScalar2RegMisc) \ +#define VISITOR_LIST_THAT_RETURN(V) \ + V(SVEBroadcastBitmaskImm) \ + V(Unallocated) \ + V(Unimplemented) + +#define SIM_AUD_VISITOR_LIST_THAT_RETURN(V) \ V(NEONScalar2RegMiscFP16) \ - V(NEONScalar3Diff) \ - V(NEONScalar3Same) \ - V(NEONScalar3SameExtra) \ V(NEONScalar3SameFP16) \ - V(NEONScalarByIndexedElement) \ - V(NEONScalarCopy) \ - V(NEONScalarPairwise) \ - V(NEONScalarShiftImmediate) \ - V(NEONShiftImmediate) \ - V(NEONTable) \ - V(PCRelAddressing) \ - V(RotateRightIntoFlags) \ - V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \ - V(SVE32BitGatherLoad_VectorPlusImm) \ + V(NEONScalar3SameExtra) \ V(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets) \ V(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets) \ + V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \ V(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets) \ - V(SVE32BitGatherPrefetch_VectorPlusImm) \ V(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets) \ V(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets) \ - V(SVE32BitScatterStore_VectorPlusImm) \ V(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets) \ V(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsets) \ V(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets) \ V(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets) \ - V(SVE64BitGatherLoad_VectorPlusImm) \ - V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \ - V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \ - V(SVE64BitGatherPrefetch_VectorPlusImm) \ V(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets) \ V(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets) \ V(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets) \ V(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets) \ - V(SVE64BitScatterStore_VectorPlusImm) \ - V(SVEAddressGeneration) \ - V(SVEBitwiseLogicalUnpredicated) \ - V(SVEBitwiseShiftUnpredicated) \ + V(SVEBitwiseLogical_Predicated) \ + V(SVEBitwiseShiftByVector_Predicated) \ + V(SVEConditionallyBroadcastElementToVector) \ + V(SVEConditionallyExtractElementToSIMDFPScalar) \ + V(SVEConstructivePrefix_Unpredicated) \ + V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \ + V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \ + V(SVEContiguousStore_ScalarPlusScalar) \ + V(SVEExtractElementToSIMDFPScalarRegister) \ V(SVEFFRInitialise) \ V(SVEFFRWriteFromPredicate) \ - V(SVEFPAccumulatingReduction) \ - V(SVEFPArithmeticUnpredicated) \ - V(SVEFPCompareVectors) \ - V(SVEFPCompareWithZero) \ - V(SVEFPComplexAddition) \ - V(SVEFPComplexMulAdd) \ + V(SVEFPConvertToInt) \ + V(SVEInsertSIMDFPScalarRegister) \ + V(SVEIntAddSubtractVectors_Predicated) \ + V(SVEIntMinMaxDifference_Predicated) \ + V(SVEIntMinMaxImm_Unpredicated) \ + V(SVEIntMulImm_Unpredicated) \ + V(SVEIntMulVectors_Predicated) \ + V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \ + V(SVELoadMultipleStructures_ScalarPlusImm) \ + V(SVELoadMultipleStructures_ScalarPlusScalar) \ + V(SVEPartitionBreakCondition) \ + V(SVEPermutePredicateElements) \ + V(SVEPredicateFirstActive) \ + V(SVEPredicateReadFromFFR_Unpredicated) \ + V(SVEPredicateTest) \ + V(SVEPredicateZero) \ + V(SVEPropagateBreakToNextPartition) \ + V(SVEStoreMultipleStructures_ScalarPlusImm) \ + V(SVEStoreMultipleStructures_ScalarPlusScalar) \ + V(SVETableLookup) \ + V(SVEUnpackPredicateElements) \ + V(SVEVectorSplice) \ V(SVEFPComplexMulAddIndex) \ - V(SVEFPFastReduction) \ V(SVEFPMulIndex) \ - V(SVEFPMulAdd) \ V(SVEFPMulAddIndex) \ - V(SVEFPUnaryOpUnpredicated) \ V(SVEIncDecByPredicateCount) \ - V(SVEIndexGeneration) \ V(SVEIntArithmeticUnpredicated) \ V(SVEIntCompareSignedImm) \ V(SVEIntCompareUnsignedImm) \ V(SVEIntCompareVectors) \ V(SVEIntMulAddPredicated) \ - V(SVEIntMulAddUnpredicated) \ - V(SVEIntReduction) \ - V(SVEIntUnaryArithmeticPredicated) \ V(SVEMovprfx) \ - V(SVEMulIndex) \ V(SVEPermuteVectorExtract) \ V(SVEPermuteVectorInterleaving) \ V(SVEPredicateCount) \ - V(SVEPredicateLogical) \ + V(SVEPredicateNextActive) \ + V(SVEPredicateReadFromFFR_Predicated) \ V(SVEPropagateBreak) \ V(SVEStackFrameAdjustment) \ V(SVEStackFrameSize) \ - V(SVEVectorSelect) \ - V(SVEBitwiseLogical_Predicated) \ - V(SVEBitwiseLogicalWithImm_Unpredicated) \ - V(SVEBitwiseShiftByImm_Predicated) \ - V(SVEBitwiseShiftByVector_Predicated) \ - V(SVEBitwiseShiftByWideElements_Predicated) \ - V(SVEBroadcastBitmaskImm) \ - V(SVEBroadcastFPImm_Unpredicated) \ - V(SVEBroadcastGeneralRegister) \ - V(SVEBroadcastIndexElement) \ - V(SVEBroadcastIntImm_Unpredicated) \ - V(SVECompressActiveElements) \ - V(SVEConditionallyBroadcastElementToVector) \ - V(SVEConditionallyExtractElementToSIMDFPScalar) \ - V(SVEConditionallyExtractElementToGeneralRegister) \ - V(SVEConditionallyTerminateScalars) \ - V(SVEConstructivePrefix_Unpredicated) \ - V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \ - V(SVEContiguousLoad_ScalarPlusImm) \ V(SVEContiguousLoad_ScalarPlusScalar) \ - V(SVEContiguousNonFaultLoad_ScalarPlusImm) \ - V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \ - V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \ - V(SVEContiguousNonTemporalStore_ScalarPlusImm) \ - V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \ - V(SVEContiguousPrefetch_ScalarPlusImm) \ - V(SVEContiguousPrefetch_ScalarPlusScalar) \ - V(SVEContiguousStore_ScalarPlusImm) \ - V(SVEContiguousStore_ScalarPlusScalar) \ - V(SVECopySIMDFPScalarRegisterToVector_Predicated) \ - V(SVECopyFPImm_Predicated) \ - V(SVECopyGeneralRegisterToVector_Predicated) \ - V(SVECopyIntImm_Predicated) \ - V(SVEElementCount) \ - V(SVEExtractElementToSIMDFPScalarRegister) \ - V(SVEExtractElementToGeneralRegister) \ - V(SVEFPArithmetic_Predicated) \ - V(SVEFPArithmeticWithImm_Predicated) \ - V(SVEFPConvertPrecision) \ - V(SVEFPConvertToInt) \ - V(SVEFPExponentialAccelerator) \ - V(SVEFPRoundToIntegralValue) \ - V(SVEFPTrigMulAddCoefficient) \ - V(SVEFPTrigSelectCoefficient) \ - V(SVEFPUnaryOp) \ - V(SVEIncDecRegisterByElementCount) \ - V(SVEIncDecVectorByElementCount) \ - V(SVEInsertSIMDFPScalarRegister) \ - V(SVEInsertGeneralRegister) \ - V(SVEIntAddSubtractImm_Unpredicated) \ - V(SVEIntAddSubtractVectors_Predicated) \ - V(SVEIntCompareScalarCountAndLimit) \ - V(SVEIntConvertToFP) \ - V(SVEIntDivideVectors_Predicated) \ - V(SVEIntMinMaxImm_Unpredicated) \ - V(SVEIntMinMaxDifference_Predicated) \ - V(SVEIntMulImm_Unpredicated) \ - V(SVEIntMulVectors_Predicated) \ - V(SVELoadAndBroadcastElement) \ - V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \ - V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \ - V(SVELoadMultipleStructures_ScalarPlusImm) \ - V(SVELoadMultipleStructures_ScalarPlusScalar) \ - V(SVELoadPredicateRegister) \ - V(SVELoadVectorRegister) \ - V(SVEPartitionBreakCondition) \ - V(SVEPermutePredicateElements) \ - V(SVEPredicateFirstActive) \ + V(RotateRightIntoFlags) \ + V(EvaluateIntoFlags) \ + V(ConditionalCompareRegister) \ + V(ConditionalCompareImmediate) \ + V(PCRelAddressing) \ + V(UnconditionalBranch) \ + V(DataProcessing1Source) \ + V(CompareBranch) \ + V(TestBranch) \ + V(LoadStoreRCpcUnscaledOffset) \ + V(LoadStoreUnscaledOffset) \ + V(LoadLiteral) \ + V(LoadStorePairNonTemporal) \ + V(LoadStorePAC) \ + V(FPCompare) \ + V(FPConditionalCompare) \ + V(FPConditionalSelect) \ + V(FPDataProcessing2Source) \ + V(FPDataProcessing3Source) \ + V(FPIntegerConvert) \ + V(FPFixedPointConvert) \ + V(Exception) \ + V(Crypto2RegSHA) \ + V(Crypto3RegSHA) \ + V(CryptoAES) \ + V(NEON2RegMiscFP16) \ + V(SVEContiguousLoad_ScalarPlusImm) \ V(SVEPredicateInitialize) \ - V(SVEPredicateNextActive) \ - V(SVEPredicateReadFromFFR_Predicated) \ - V(SVEPredicateReadFromFFR_Unpredicated) \ - V(SVEPredicateTest) \ - V(SVEPredicateZero) \ - V(SVEPropagateBreakToNextPartition) \ + V(SVEIndexGeneration) \ + V(SVEAddressGeneration) \ + V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \ + V(SVEIntAddSubtractImm_Unpredicated) \ + V(SVEIntCompareScalarCountAndLimit) \ + V(FPImmediate) \ + V(FPDataProcessing1Source) \ + V(NEONModifiedImmediate) \ + V(NEONTable) \ + V(SVEIntReduction) \ + V(SVEMulIndex) \ + V(NEON3SameFP16) \ + V(NEONLoadStoreSingleStruct) \ + V(NEONLoadStoreSingleStructPostIndex) \ + V(NEONLoadStoreMultiStructPostIndex) \ + V(LoadStorePreIndex) \ + V(LoadStorePostIndex) \ + V(LoadStoreUnsignedOffset) \ + V(LoadStoreRegisterOffset) \ + V(LoadStorePairPostIndex) \ + V(LoadStorePairOffset) \ + V(LoadStorePairPreIndex) \ + V(SVEBitwiseShiftByWideElements_Predicated) \ + V(NEONScalarPairwise) \ + V(SVEFPUnaryOp) \ + V(SVEFPRoundToIntegralValue) \ + V(SVEFPUnaryOpUnpredicated) \ + V(SVEFPMulAdd) \ + V(SVEFPFastReduction) \ + V(SVEFPComplexMulAdd) \ + V(SVEFPComplexAddition) \ + V(SVEFPCompareWithZero) \ + V(SVEFPCompareVectors) \ + V(SVEFPArithmeticUnpredicated) \ + V(SVEFPAccumulatingReduction) \ + V(SVEIntUnaryArithmeticPredicated) \ + V(SVEBitwiseShiftUnpredicated) \ + V(SVEUnpackVectorElements) \ + V(SVEIntConvertToFP) \ + V(SVEReverseWithinElements) \ V(SVEReversePredicateElements) \ V(SVEReverseVectorElements) \ - V(SVEReverseWithinElements) \ - V(SVESaturatingIncDecRegisterByElementCount) \ - V(SVESaturatingIncDecVectorByElementCount) \ - V(SVEStoreMultipleStructures_ScalarPlusImm) \ - V(SVEStoreMultipleStructures_ScalarPlusScalar) \ - V(SVEStorePredicateRegister) \ - V(SVEStoreVectorRegister) \ - V(SVETableLookup) \ - V(SVEUnpackPredicateElements) \ - V(SVEUnpackVectorElements) \ - V(SVEVectorSplice) \ - V(System) \ - V(TestBranch) \ - V(Unallocated) \ - V(UnconditionalBranch) \ + V(SVEInsertGeneralRegister) \ + V(SVEFPTrigSelectCoefficient) \ + V(SVEFPTrigMulAddCoefficient) \ + V(SVEFPExponentialAccelerator) \ + V(SVEFPArithmetic_Predicated) \ + V(SVEFPArithmeticWithImm_Predicated) \ + V(SVEBitwiseLogicalWithImm_Unpredicated) \ V(UnconditionalBranchToRegister) \ - V(Unimplemented) + V(NEONExtract) \ + V(ConditionalSelect) \ + V(LogicalImmediate) \ + V(AddSubImmediate) \ + V(AddSubShifted) \ + V(AddSubExtended) \ + V(LogicalShifted) \ + V(Extract) \ + V(DataProcessing2Source) \ + V(DataProcessing3Source) \ + V(ConditionalBranch) \ + V(Bitfield) \ + V(AtomicMemory) \ + V(SVEVectorSelect) \ + V(SVEPredicateLogical) \ + V(SVEIntDivideVectors_Predicated) \ + V(SVEBroadcastIntImm_Unpredicated) \ + V(SVEBroadcastFPImm_Unpredicated) \ + V(SVEBroadcastGeneralRegister) \ + V(SVECompressActiveElements) \ + V(SVEConditionallyTerminateScalars) \ + V(SVEConditionallyExtractElementToGeneralRegister) \ + V(SVEBitwiseShiftByImm_Predicated) \ + V(SVECopyGeneralRegisterToVector_Predicated) \ + V(SVECopyIntImm_Predicated) \ + V(SVECopySIMDFPScalarRegisterToVector_Predicated) \ + V(SVECopyFPImm_Predicated) \ + V(SVEExtractElementToGeneralRegister) \ + V(SVEIntMulAddUnpredicated) \ + V(SVEContiguousStore_ScalarPlusImm) \ + V(SVEContiguousPrefetch_ScalarPlusScalar) \ + V(SVEContiguousPrefetch_ScalarPlusImm) \ + V(SVEContiguousNonFaultLoad_ScalarPlusImm) \ + V(SVEBitwiseLogicalUnpredicated) \ + V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \ + V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \ + V(SVE64BitGatherPrefetch_VectorPlusImm) \ + V(SVE32BitGatherPrefetch_VectorPlusImm) \ + V(SVELoadVectorRegister) \ + V(SVEStoreVectorRegister) \ + V(SVELoadPredicateRegister) \ + V(SVEStorePredicateRegister) \ + V(SVEFPConvertPrecision) \ + V(SVE32BitGatherLoad_VectorPlusImm) \ + V(SVE32BitScatterStore_VectorPlusImm) \ + V(SVE64BitScatterStore_VectorPlusImm) \ + V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \ + V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \ + V(SVEContiguousNonTemporalStore_ScalarPlusImm) \ + V(SVELoadAndBroadcastElement) \ + V(NEONPerm) \ + V(NEONLoadStoreMultiStruct) \ + V(NEON3Same) \ + V(NEON3SameExtra) \ + V(NEON2RegMisc) \ + V(NEONByIndexedElement) \ + V(SVE64BitGatherLoad_VectorPlusImm) \ + V(NEONShiftImmediate) \ + V(NEONCopy) \ + V(NEONScalar2RegMisc) \ + V(NEONScalar3Diff) \ + V(NEONScalar3Same) \ + V(NEONScalarCopy) \ + V(NEONScalarByIndexedElement) \ + V(NEONAcrossLanes) \ + V(NEONScalarShiftImmediate) \ + V(NEON3Different) \ + V(MoveWideImmediate) \ + V(SVEElementCount) \ + V(SVEIncDecRegisterByElementCount) \ + V(SVEIncDecVectorByElementCount) \ + V(SVESaturatingIncDecVectorByElementCount) \ + V(SVESaturatingIncDecRegisterByElementCount) \ + V(LoadStoreExclusive) \ + V(SVEBroadcastIndexElement) \ + V(System) \ + V(AddSubWithCarry) #define VISITOR_LIST_THAT_DONT_RETURN(V) V(Reserved) @@ -271,6 +275,10 @@ VISITOR_LIST_THAT_RETURN(V) \ VISITOR_LIST_THAT_DONT_RETURN(V) +#define SIM_AUD_VISITOR_LIST(V) \ + VISITOR_LIST(V) \ + SIM_AUD_VISITOR_LIST_THAT_RETURN(V) + namespace vixl { namespace aarch64 { @@ -311,7 +319,10 @@ class CompiledDecodeNode; // handles the instruction. class Decoder { public: - Decoder() { ConstructDecodeGraph(); } + Decoder() { + ConstructDecodeGraph(); + PopulatePerInstructionUnallocatedMap(&form_to_unalloc_); + } // Top-level wrappers around the actual decoding function. void Decode(const Instruction* instr); @@ -392,6 +403,13 @@ class Decoder { // Map of node names to DecodeNodes. std::map decode_nodes_; + + // Map from instruction form strings to a mask/value of encodings for that + // form. + using FormToUnallocMap = std::unordered_multimap; + FormToUnallocMap form_to_unalloc_; + + static void PopulatePerInstructionUnallocatedMap(FormToUnallocMap* ftm); }; typedef void (Decoder::*DecodeFnPtr)(const Instruction*); @@ -471,7 +489,7 @@ class CompiledDecodeNode { bool IsLeafNode() const { VIXL_ASSERT(((instruction_name_ == "node") && (bit_extract_fn_ != NULL)) || ((instruction_name_ != "node") && (bit_extract_fn_ == NULL))); - return instruction_name_ != "node"; + return bit_extract_fn_ == NULL; } // Get a pointer to the next node required in the decode process, based on the diff --git a/3rdparty/vixl/include/vixl/aarch64/decoder-constants-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/decoder-constants-aarch64.h index af50a55270..9426cab3b0 100644 --- a/3rdparty/vixl/include/vixl/aarch64/decoder-constants-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/decoder-constants-aarch64.h @@ -1923,8 +1923,24 @@ static const DecodeMapping kDecodeMapping[] = { }, { "_kjsrkm", - {18, 17, 16, 13, 12, 11, 10, 9, 8, 7, 4, 3, 2, 1, 0}, - { {"000000000011111"_b, "_zztypv"}, + {11, 10, 9, 8}, + { {"0000"_b, "_flags"}, + {"xxx1"_b, "_msrimm"}, + {"xx1x"_b, "_msrimm"}, + {"x1xx"_b, "_msrimm"}, + {"1xxx"_b, "_msrimm"}, + }, + }, + + { "_msrimm", + {13, 12, 4, 3, 2, 1, 0}, + { {"0011111"_b, "msr_si_pstate"}, + }, + }, + + { "_flags", + {18, 17, 16, 13, 12, 7, 4, 3, 2, 1, 0}, + { {"00000011111"_b, "_zztypv"}, }, }, diff --git a/3rdparty/vixl/include/vixl/aarch64/decoder-visitor-map-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/decoder-visitor-map-aarch64.h index b4b39f559a..e26f01f18d 100644 --- a/3rdparty/vixl/include/vixl/aarch64/decoder-visitor-map-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/decoder-visitor-map-aarch64.h @@ -33,152 +33,561 @@ // the component's function, so this map initialisation will no longer be // shared. -#define DEFAULT_FORM_TO_VISITOR_MAP(VISITORCLASS) \ - {"abs_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"addpl_r_ri"_h, &VISITORCLASS::VisitSVEStackFrameAdjustment}, \ - {"addvl_r_ri"_h, &VISITORCLASS::VisitSVEStackFrameAdjustment}, \ - {"add_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ - {"add_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"add_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"adr_z_az_d_s32_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ - {"adr_z_az_d_u32_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ - {"adr_z_az_sd_same_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ - {"ands_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"andv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"and_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ +#define DEFAULT_FORM_TO_VISITOR_MAP(VISITORCLASS) \ + {"dupm_z_i"_h, &VISITORCLASS::VisitSVEBroadcastBitmaskImm}, \ + {"udf_only_perm_undef"_h, &VISITORCLASS::VisitReserved}, \ + {"bfdot_asimdelem_e"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfdot_asimdsame2_d"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlal_asimdelem_f"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlal_asimdsame2_f"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmmla_asimdsame2_e"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"dsb_bon_barriers"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"ld64b_64l_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"ldgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"st64b_64l_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"st64bv_64_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"st64bv0_64_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"stgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"stzgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"tcancel_ex_exception"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"tcommit_only_barriers"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"tstart_br_systemresult"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"ttest_br_systemresult"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"wfet_only_systeminstrswithreg"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"wfit_only_systeminstrswithreg"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfdot_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfdot_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlalb_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlalb_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlalt_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmlalt_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"bfmmla_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, { \ + "unallocated"_h, &VISITORCLASS::VisitUnallocated \ + } + +#define SIM_AUD_VISITOR_MAP(VISITORCLASS) \ + {"autia1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"autiasp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"autiaz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"autib1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"autibsp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"autibz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"axflag_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ + {"cfinv_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ + {"csdb_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"dgh_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"esb_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"isb_bi_barriers"_h, &VISITORCLASS::VisitSystem}, \ + {"nop_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"pacia1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"paciasp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"paciaz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"pacib1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"pacibsp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"pacibz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"sev_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"sevl_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"ssbb_only_barriers"_h, &VISITORCLASS::VisitSystem}, \ + {"wfe_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"wfi_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"xaflag_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ + {"xpaclri_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"yield_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"mla_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"mls_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"mul_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"saba_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sabd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"shadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"shsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"smaxp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"smax_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sminp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"smin_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"srhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uaba_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uabd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uhsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"umaxp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"umax_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uminp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"umin_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"urhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"and_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"bic_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"bif_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"bit_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"bsl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"eor_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"orr_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"orn_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"pmul_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"fmlal2_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"fmlal_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"fmlsl2_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"fmlsl_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"pmull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"ushll_asimdshf_l"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sshll_asimdshf_l"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"shrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"rshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sqshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sqrshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sqshrun_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sqrshrun_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"uqshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"uqrshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sri_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"srshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"srsra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"ssra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"urshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"ursra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"ushr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"usra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"scvtf_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"ucvtf_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"fcvtzs_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"fcvtzu_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ + {"sqdmlal_asisdelem_l"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqdmlsl_asisdelem_l"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqdmull_asisdelem_l"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqdmulh_asisdelem_r"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqrdmlah_asisdelem_r"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqrdmlsh_asisdelem_r"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"sqrdmulh_asisdelem_r"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fabd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"facge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"facgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"fcmeq_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"fcmge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"fcmgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"fmulx_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"frecps_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"frsqrts_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmeq_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmhi_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmhs_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"cmtst_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"add_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqadd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqdmulh_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqrdmulh_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqrshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqsub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"srshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"uqadd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"uqrshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"uqshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"uqsub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"urshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"ushl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ + {"sqrdmlah_asisdsame2_only"_h, \ + &VISITORCLASS::VisitNEONScalar3SameExtra}, \ + {"sqrdmlsh_asisdsame2_only"_h, \ + &VISITORCLASS::VisitNEONScalar3SameExtra}, \ + {"fmaxnmv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fmaxv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fminnmv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fminv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fmaxnmv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fminnmv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fmaxv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"fminv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"shl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sli_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sri_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"srshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"srsra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"ssra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"urshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"ursra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"ushr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"usra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sqrshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sqrshrun_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sqshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sqshrun_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"uqrshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"uqshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"cmeq_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"cmge_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"cmgt_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"cmle_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"cmlt_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"abs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"neg_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcmeq_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcmge_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcmgt_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcmle_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcmlt_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtas_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtau_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtms_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtmu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtns_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtnu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtps_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtpu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtxn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtzs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"fcvtzu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"frecpe_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"frecpx_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"frsqrte_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"scvtf_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"ucvtf_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"ld1rqb_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ + {"ld1rqd_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ + {"ld1rqh_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ + {"ld1rqw_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ + {"fcmeq_asisdmiscfp16_fz"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcmge_asisdmiscfp16_fz"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcmgt_asisdmiscfp16_fz"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcmle_asisdmiscfp16_fz"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcmlt_asisdmiscfp16_fz"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtas_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtau_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtms_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtmu_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtns_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtnu_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtps_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtpu_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtzs_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fcvtzu_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"frecpe_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"frecpx_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"frsqrte_asisdmiscfp16_r"_h, \ + &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"scvtf_asisdmiscfp16_r"_h, &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"ucvtf_asisdmiscfp16_r"_h, &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ + {"fabd_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"facge_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"facgt_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"fcmeq_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"fcmge_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"fcmgt_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"fmulx_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"frecps_asisdsamefp16_only"_h, \ + &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"frsqrts_asisdsamefp16_only"_h, \ + &VISITORCLASS::VisitNEONScalar3SameFP16}, \ + {"ld1h_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ + {"ld1sh_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ + {"ldff1h_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ + {"ldff1sh_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ + {"ld1w_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets}, \ + {"ldff1w_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets}, \ + {"ld1b_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ld1h_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ld1sb_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ld1sh_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ld1w_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ldff1b_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ldff1h_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ldff1sb_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ldff1sh_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"ldff1w_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ + {"prfb_i_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ + {"prfd_i_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ + {"prfh_i_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ + {"prfw_i_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ + {"st1h_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets}, \ + {"st1w_z_p_bz_s_x32_scaled"_h, \ + &VISITORCLASS::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets}, \ + {"st1b_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ + {"st1h_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ + {"st1w_z_p_bz_s_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ + {"ld1d_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ld1h_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ld1sh_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ld1sw_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ld1w_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ldff1d_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ldff1h_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ldff1sh_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ldff1sw_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ldff1w_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ + {"ld1d_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ld1h_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ld1sh_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ld1sw_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ld1w_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ldff1d_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ldff1h_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ldff1sh_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ldff1sw_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ldff1w_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ + {"ld1b_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1d_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1h_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1sb_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1sh_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1sw_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1w_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1b_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1d_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1h_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1sb_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1sh_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1sw_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ldff1w_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ + {"ld1b_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1d_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1h_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1sb_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1sh_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1sw_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ld1w_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1b_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1d_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1h_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1sb_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1sh_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1sw_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"ldff1w_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"st1d_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ + {"st1h_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ + {"st1w_z_p_bz_d_64_scaled"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ + {"st1b_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ + {"st1d_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ + {"st1h_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ + {"st1w_z_p_bz_d_64_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ + {"st1d_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"st1h_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"st1w_z_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"st1b_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"st1d_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"st1h_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ + {"st1w_z_p_bz_d_x32_unscaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ {"and_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ - {"and_z_zi"_h, \ - &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ - {"and_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ - {"asrd_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ + {"bic_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ + {"eor_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ + {"orr_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ {"asrr_z_p_zz"_h, \ &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"asr_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ - {"asr_z_p_zw"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ {"asr_z_p_zz"_h, \ &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"asr_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"asr_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"bics_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"bic_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"bic_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ - {"bic_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ - {"brkas_p_p_p_z"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ - {"brka_p_p_p"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ - {"brkbs_p_p_p_z"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ - {"brkb_p_p_p"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ - {"brkns_p_p_pp"_h, \ - &VISITORCLASS::VisitSVEPropagateBreakToNextPartition}, \ - {"brkn_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreakToNextPartition}, \ - {"brkpas_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ - {"brkpa_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ - {"brkpbs_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ - {"brkpb_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ - {"clasta_r_p_z"_h, \ - &VISITORCLASS::VisitSVEConditionallyExtractElementToGeneralRegister}, \ - {"clasta_v_p_z"_h, \ - &VISITORCLASS::VisitSVEConditionallyExtractElementToSIMDFPScalar}, \ + {"lslr_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ + {"lsl_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ + {"lsrr_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ + {"lsr_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ {"clasta_z_p_zz"_h, \ &VISITORCLASS::VisitSVEConditionallyBroadcastElementToVector}, \ - {"clastb_r_p_z"_h, \ - &VISITORCLASS::VisitSVEConditionallyExtractElementToGeneralRegister}, \ - {"clastb_v_p_z"_h, \ - &VISITORCLASS::VisitSVEConditionallyExtractElementToSIMDFPScalar}, \ {"clastb_z_p_zz"_h, \ &VISITORCLASS::VisitSVEConditionallyBroadcastElementToVector}, \ - {"cls_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"clz_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"cmpeq_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmpeq_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpeq_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpge_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmpge_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpge_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpgt_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmpgt_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpgt_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmphi_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ - {"cmphi_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmphi_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmphs_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ - {"cmphs_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmphs_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmple_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmple_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmplo_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ - {"cmplo_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpls_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ - {"cmpls_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmplt_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmplt_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpne_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ - {"cmpne_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cmpne_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ - {"cnot_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"cntb_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ - {"cntd_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ - {"cnth_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ - {"cntp_r_p_p"_h, &VISITORCLASS::VisitSVEPredicateCount}, \ - {"cntw_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ - {"cnt_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"compact_z_p_z"_h, &VISITORCLASS::VisitSVECompressActiveElements}, \ - {"cpy_z_o_i"_h, &VISITORCLASS::VisitSVECopyIntImm_Predicated}, \ - {"cpy_z_p_i"_h, &VISITORCLASS::VisitSVECopyIntImm_Predicated}, \ - {"cpy_z_p_r"_h, \ - &VISITORCLASS::VisitSVECopyGeneralRegisterToVector_Predicated}, \ - {"cpy_z_p_v"_h, \ - &VISITORCLASS::VisitSVECopySIMDFPScalarRegisterToVector_Predicated}, \ - {"ctermeq_rr"_h, &VISITORCLASS::VisitSVEConditionallyTerminateScalars}, \ - {"ctermne_rr"_h, &VISITORCLASS::VisitSVEConditionallyTerminateScalars}, \ - {"decb_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"decd_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"decd_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ - {"dech_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"dech_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ - {"decp_r_p_r"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"decp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"decw_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"decw_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ - {"dupm_z_i"_h, &VISITORCLASS::VisitSVEBroadcastBitmaskImm}, \ - {"dup_z_i"_h, &VISITORCLASS::VisitSVEBroadcastIntImm_Unpredicated}, \ - {"dup_z_r"_h, &VISITORCLASS::VisitSVEBroadcastGeneralRegister}, \ - {"dup_z_zi"_h, &VISITORCLASS::VisitSVEBroadcastIndexElement}, \ - {"eors_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"eorv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"eor_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"eor_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ - {"eor_z_zi"_h, \ - &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ - {"eor_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ - {"ext_z_zi_des"_h, &VISITORCLASS::VisitSVEPermuteVectorExtract}, \ - {"fabd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fabs_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"facge_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"facgt_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fadda_v_p_z"_h, &VISITORCLASS::VisitSVEFPAccumulatingReduction}, \ - {"faddv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ - {"fadd_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fadd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fadd_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ - {"fcadd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPComplexAddition}, \ - {"fcmeq_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmeq_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fcmge_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmge_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fcmgt_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmgt_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fcmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPComplexMulAdd}, \ - {"fcmla_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPComplexMulAddIndex}, \ - {"fcmla_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPComplexMulAddIndex}, \ - {"fcmle_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmlt_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmne_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ - {"fcmne_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fcmuo_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ - {"fcpy_z_p_i"_h, &VISITORCLASS::VisitSVECopyFPImm_Predicated}, \ + {"clasta_v_p_z"_h, \ + &VISITORCLASS::VisitSVEConditionallyExtractElementToSIMDFPScalar}, \ + {"clastb_v_p_z"_h, \ + &VISITORCLASS::VisitSVEConditionallyExtractElementToSIMDFPScalar}, \ + {"movprfx_z_z"_h, \ + &VISITORCLASS::VisitSVEConstructivePrefix_Unpredicated}, \ + {"ldnt1b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ + {"ldnt1d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ + {"ldnt1h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ + {"ldnt1w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ + {"stnt1b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ + {"stnt1d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ + {"stnt1h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ + {"stnt1w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ + {"st1b_z_p_br"_h, \ + &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ + {"st1d_z_p_br"_h, \ + &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ + {"st1h_z_p_br"_h, \ + &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ + {"st1w_z_p_br"_h, \ + &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ + {"lasta_v_p_z"_h, \ + &VISITORCLASS::VisitSVEExtractElementToSIMDFPScalarRegister}, \ + {"lastb_v_p_z"_h, \ + &VISITORCLASS::VisitSVEExtractElementToSIMDFPScalarRegister}, \ + {"setffr_f"_h, &VISITORCLASS::VisitSVEFFRInitialise}, \ + {"wrffr_f_p"_h, &VISITORCLASS::VisitSVEFFRWriteFromPredicate}, \ {"fcvtzs_z_p_z_d2w"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ {"fcvtzs_z_p_z_d2x"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ {"fcvtzs_z_p_z_fp162h"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ @@ -193,114 +602,235 @@ {"fcvtzu_z_p_z_fp162x"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ {"fcvtzu_z_p_z_s2w"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ {"fcvtzu_z_p_z_s2x"_h, &VISITORCLASS::VisitSVEFPConvertToInt}, \ - {"fcvt_z_p_z_d2h"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fcvt_z_p_z_d2s"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fcvt_z_p_z_h2d"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fcvt_z_p_z_h2s"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fcvt_z_p_z_s2d"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fcvt_z_p_z_s2h"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ - {"fdivr_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fdiv_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fdup_z_i"_h, &VISITORCLASS::VisitSVEBroadcastFPImm_Unpredicated}, \ - {"fexpa_z_z"_h, &VISITORCLASS::VisitSVEFPExponentialAccelerator}, \ - {"fmad_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fmaxnmv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ - {"fmaxnm_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fmaxnm_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fmaxv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ - {"fmax_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fmax_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fminnmv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ - {"fminnm_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fminnm_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fminv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ - {"fmin_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fmin_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fmla_z_zzzi_d"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmla_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmla_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmls_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fmls_z_zzzi_d"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmls_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmls_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ - {"fmsb_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fmulx_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fmul_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fmul_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fmul_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"insr_z_v"_h, &VISITORCLASS::VisitSVEInsertSIMDFPScalarRegister}, \ + {"add_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ + {"subr_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ + {"sub_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ + {"sabd_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"smax_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"smin_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"uabd_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"umax_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"umin_z_p_zz"_h, \ + &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ + {"smax_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ + {"smin_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ + {"umax_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ + {"umin_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ + {"mul_z_zi"_h, &VISITORCLASS::VisitSVEIntMulImm_Unpredicated}, \ + {"mul_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ + {"smulh_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ + {"umulh_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ + {"ld2b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld2d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld2h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld2w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld3b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld3d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld3h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld3w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld4b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld4d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld4h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld4w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ + {"ld2b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld2d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld2h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld2w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld3b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld3d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld3h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld3w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld4b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld4d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld4h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"ld4w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ + {"brkas_p_p_p_z"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ + {"brka_p_p_p"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ + {"brkbs_p_p_p_z"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ + {"brkb_p_p_p"_h, &VISITORCLASS::VisitSVEPartitionBreakCondition}, \ + {"trn1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"trn2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"uzp1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"uzp2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"zip1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"zip2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ + {"pfirst_p_p_p"_h, &VISITORCLASS::VisitSVEPredicateFirstActive}, \ + {"rdffr_p_f"_h, \ + &VISITORCLASS::VisitSVEPredicateReadFromFFR_Unpredicated}, \ + {"ptest_p_p"_h, &VISITORCLASS::VisitSVEPredicateTest}, \ + {"pfalse_p"_h, &VISITORCLASS::VisitSVEPredicateZero}, \ + {"brkns_p_p_pp"_h, \ + &VISITORCLASS::VisitSVEPropagateBreakToNextPartition}, \ + {"brkn_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreakToNextPartition}, \ + {"st2b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st2d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st2h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st2w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st3b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st3d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st3h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st3w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st4b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st4d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st4h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st4w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ + {"st2b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st2d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st2h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st2w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st3b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st3d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st3h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st3w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st4b_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st4d_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st4h_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"st4w_z_p_br_contiguous"_h, \ + &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ + {"tbl_z_zz_1"_h, &VISITORCLASS::VisitSVETableLookup}, \ + {"punpkhi_p_p"_h, &VISITORCLASS::VisitSVEUnpackPredicateElements}, \ + {"punpklo_p_p"_h, &VISITORCLASS::VisitSVEUnpackPredicateElements}, \ + {"splice_z_p_zz_des"_h, &VISITORCLASS::VisitSVEVectorSplice}, \ + {"fcmla_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPComplexMulAddIndex}, \ + {"fcmla_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPComplexMulAddIndex}, \ {"fmul_z_zzi_d"_h, &VISITORCLASS::VisitSVEFPMulIndex}, \ {"fmul_z_zzi_h"_h, &VISITORCLASS::VisitSVEFPMulIndex}, \ {"fmul_z_zzi_s"_h, &VISITORCLASS::VisitSVEFPMulIndex}, \ - {"fneg_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"fnmad_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fnmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fnmls_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"fnmsb_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ - {"frecpe_z_z"_h, &VISITORCLASS::VisitSVEFPUnaryOpUnpredicated}, \ - {"frecps_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ - {"frecpx_z_p_z"_h, &VISITORCLASS::VisitSVEFPUnaryOp}, \ - {"frinta_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frinti_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frintm_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frintn_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frintp_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frintx_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frintz_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ - {"frsqrte_z_z"_h, &VISITORCLASS::VisitSVEFPUnaryOpUnpredicated}, \ - {"frsqrts_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ - {"fscale_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fsqrt_z_p_z"_h, &VISITORCLASS::VisitSVEFPUnaryOp}, \ - {"fsubr_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fsubr_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fsub_z_p_zs"_h, \ - &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ - {"fsub_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ - {"fsub_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ - {"ftmad_z_zzi"_h, &VISITORCLASS::VisitSVEFPTrigMulAddCoefficient}, \ - {"ftsmul_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ - {"ftssel_z_zz"_h, &VISITORCLASS::VisitSVEFPTrigSelectCoefficient}, \ - {"incb_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"incd_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"incd_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ - {"inch_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"inch_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"fmla_z_zzzi_d"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"fmla_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"fmla_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"fmls_z_zzzi_d"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"fmls_z_zzzi_h"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"fmls_z_zzzi_s"_h, &VISITORCLASS::VisitSVEFPMulAddIndex}, \ + {"decp_r_p_r"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"decp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ {"incp_r_p_r"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ {"incp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"incw_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ - {"incw_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ - {"index_z_ii"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ - {"index_z_ir"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ - {"index_z_ri"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ - {"index_z_rr"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ - {"insr_z_r"_h, &VISITORCLASS::VisitSVEInsertGeneralRegister}, \ - {"insr_z_v"_h, &VISITORCLASS::VisitSVEInsertSIMDFPScalarRegister}, \ - {"lasta_r_p_z"_h, \ - &VISITORCLASS::VisitSVEExtractElementToGeneralRegister}, \ - {"lasta_v_p_z"_h, \ - &VISITORCLASS::VisitSVEExtractElementToSIMDFPScalarRegister}, \ - {"lastb_r_p_z"_h, \ - &VISITORCLASS::VisitSVEExtractElementToGeneralRegister}, \ - {"lastb_v_p_z"_h, \ - &VISITORCLASS::VisitSVEExtractElementToSIMDFPScalarRegister}, \ - {"ld1b_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1b_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ld1b_z_p_bi_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1b_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1b_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1b_z_p_bi_u8"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"sqdecp_r_p_r_sx"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"sqdecp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"sqdecp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"sqincp_r_p_r_sx"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"sqincp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"sqincp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqdecp_r_p_r_uw"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqdecp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqdecp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqincp_r_p_r_uw"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqincp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"uqincp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ + {"add_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"sqadd_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"sqsub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"sub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"uqadd_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"uqsub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ + {"cmpeq_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmpge_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmpgt_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmple_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmplt_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmpne_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareSignedImm}, \ + {"cmphi_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ + {"cmphs_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ + {"cmplo_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ + {"cmpls_p_p_zi"_h, &VISITORCLASS::VisitSVEIntCompareUnsignedImm}, \ + {"cmpeq_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpeq_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpge_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpge_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpgt_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpgt_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmphi_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmphi_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmphs_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmphs_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmple_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmplo_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpls_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmplt_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpne_p_p_zw"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"cmpne_p_p_zz"_h, &VISITORCLASS::VisitSVEIntCompareVectors}, \ + {"mad_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ + {"mla_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ + {"mls_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ + {"msb_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ + {"movprfx_z_p_z"_h, &VISITORCLASS::VisitSVEMovprfx}, \ + {"ext_z_zi_des"_h, &VISITORCLASS::VisitSVEPermuteVectorExtract}, \ + {"trn1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"trn2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"uzp1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"uzp2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"zip1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"zip2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ + {"cntp_r_p_p"_h, &VISITORCLASS::VisitSVEPredicateCount}, \ + {"pnext_p_p_p"_h, &VISITORCLASS::VisitSVEPredicateNextActive}, \ + {"rdffrs_p_p_f"_h, \ + &VISITORCLASS::VisitSVEPredicateReadFromFFR_Predicated}, \ + {"rdffr_p_p_f"_h, \ + &VISITORCLASS::VisitSVEPredicateReadFromFFR_Predicated}, \ + {"brkpas_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ + {"brkpa_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ + {"brkpbs_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ + {"brkpb_p_p_pp"_h, &VISITORCLASS::VisitSVEPropagateBreak}, \ + {"addpl_r_ri"_h, &VISITORCLASS::VisitSVEStackFrameAdjustment}, \ + {"addvl_r_ri"_h, &VISITORCLASS::VisitSVEStackFrameAdjustment}, \ + {"rdvl_r_i"_h, &VISITORCLASS::VisitSVEStackFrameSize}, \ {"ld1b_z_p_br_u16"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1b_z_p_br_u32"_h, \ @@ -309,880 +839,466 @@ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1b_z_p_br_u8"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1b_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1b_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1b_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ld1d_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1d_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1d_z_p_br_u64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1d_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ld1d_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1d_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ld1d_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1h_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1h_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ld1h_z_p_bi_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1h_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1h_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1h_z_p_br_u16"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1h_z_p_br_u32"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1h_z_p_br_u64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1h_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ld1h_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1h_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ld1h_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1h_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ - {"ld1h_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ld1rb_z_p_bi_u16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rb_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rb_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rb_z_p_bi_u8"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rd_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rh_z_p_bi_u16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rh_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rh_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rqb_z_p_bi_u8"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ - {"ld1rqb_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ - {"ld1rqd_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ - {"ld1rqd_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ - {"ld1rqh_z_p_bi_u16"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ - {"ld1rqh_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ - {"ld1rqw_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ - {"ld1rqw_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, \ - {"ld1rsb_z_p_bi_s16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rsb_z_p_bi_s32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rsb_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rsh_z_p_bi_s32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rsh_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rsw_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rw_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1rw_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ - {"ld1sb_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1sb_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ld1sb_z_p_bi_s16"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1sb_z_p_bi_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1sb_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1sb_z_p_br_s16"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1sb_z_p_br_s32"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1sb_z_p_br_s64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1sb_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1sb_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1sb_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ld1sh_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1sh_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ld1sh_z_p_bi_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1sh_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1sh_z_p_br_s32"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1sh_z_p_br_s64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1sh_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ld1sh_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1sh_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ld1sh_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1sh_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ - {"ld1sh_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ld1sw_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1sw_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1sw_z_p_br_s64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1sw_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ld1sw_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1sw_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ld1sw_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1w_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ld1w_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ld1w_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ - {"ld1w_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ld1w_z_p_br_u32"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ {"ld1w_z_p_br_u64"_h, \ &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusScalar}, \ - {"ld1w_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ld1w_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ld1w_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ld1w_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ld1w_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets}, \ - {"ld1w_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ld2b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld2b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld2d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld2d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld2h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld2h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld2w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld2w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld3b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld3b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld3d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld3d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld3h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld3h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld3w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld3w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld4b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld4b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld4d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld4d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld4h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld4h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ld4w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusImm}, \ - {"ld4w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVELoadMultipleStructures_ScalarPlusScalar}, \ - {"ldff1b_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1b_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ldff1b_z_p_br_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1b_z_p_br_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1b_z_p_br_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1b_z_p_br_u8"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1b_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1b_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1b_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ldff1d_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1d_z_p_br_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1d_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ldff1d_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1d_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ldff1d_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1h_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1h_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ldff1h_z_p_br_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1h_z_p_br_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1h_z_p_br_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1h_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ldff1h_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1h_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ldff1h_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1h_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ - {"ldff1h_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ldff1sb_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1sb_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ldff1sb_z_p_br_s16"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sb_z_p_br_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sb_z_p_br_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sb_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1sb_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1sb_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ldff1sh_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1sh_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ldff1sh_z_p_br_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sh_z_p_br_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sh_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ldff1sh_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1sh_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ldff1sh_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1sh_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets}, \ - {"ldff1sh_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ldff1sw_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1sw_z_p_br_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1sw_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ldff1sw_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1sw_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ldff1sw_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1w_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ - {"ldff1w_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ - {"ldff1w_z_p_br_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1w_z_p_br_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ - {"ldff1w_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets}, \ - {"ldff1w_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets}, \ - {"ldff1w_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets}, \ - {"ldff1w_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"ldff1w_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets}, \ - {"ldff1w_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets}, \ - {"ldnf1b_z_p_bi_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1b_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1b_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1b_z_p_bi_u8"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1d_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1h_z_p_bi_u16"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1h_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1h_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sb_z_p_bi_s16"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sb_z_p_bi_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sb_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sh_z_p_bi_s32"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sh_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1sw_z_p_bi_s64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1w_z_p_bi_u32"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnf1w_z_p_bi_u64"_h, \ - &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ - {"ldnt1b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ - {"ldnt1b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ - {"ldnt1d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ - {"ldnt1d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ - {"ldnt1h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ - {"ldnt1h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ - {"ldnt1w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ - {"ldnt1w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar}, \ - {"ldr_p_bi"_h, &VISITORCLASS::VisitSVELoadPredicateRegister}, \ - {"ldr_z_bi"_h, &VISITORCLASS::VisitSVELoadVectorRegister}, \ - {"lslr_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"lsl_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ - {"lsl_z_p_zw"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ - {"lsl_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"lsl_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"lsl_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"lsrr_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"lsr_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ - {"lsr_z_p_zw"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ - {"lsr_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEBitwiseShiftByVector_Predicated}, \ - {"lsr_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"lsr_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ - {"mad_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ - {"mla_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ - {"mls_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ - {"movprfx_z_p_z"_h, &VISITORCLASS::VisitSVEMovprfx}, \ - {"movprfx_z_z"_h, \ - &VISITORCLASS::VisitSVEConstructivePrefix_Unpredicated}, \ - {"msb_z_p_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddPredicated}, \ - {"mul_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ - {"mul_z_zi"_h, &VISITORCLASS::VisitSVEIntMulImm_Unpredicated}, \ - {"nands_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"nand_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"neg_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"nors_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"nor_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"not_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"orns_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"orn_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"orrs_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"orr_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"orr_z_p_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogical_Predicated}, \ - {"orr_z_zi"_h, \ - &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ - {"orr_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ - {"orv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"pfalse_p"_h, &VISITORCLASS::VisitSVEPredicateZero}, \ - {"pfirst_p_p_p"_h, &VISITORCLASS::VisitSVEPredicateFirstActive}, \ - {"pnext_p_p_p"_h, &VISITORCLASS::VisitSVEPredicateNextActive}, \ - {"prfb_i_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ - {"prfb_i_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ - {"prfb_i_p_bi_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ - {"prfb_i_p_br_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ - {"prfb_i_p_bz_d_64_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ - {"prfb_i_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"prfb_i_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ - {"prfd_i_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ - {"prfd_i_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ - {"prfd_i_p_bi_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ - {"prfd_i_p_br_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ - {"prfd_i_p_bz_d_64_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ - {"prfd_i_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"prfd_i_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ - {"prfh_i_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ - {"prfh_i_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ - {"prfh_i_p_bi_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ - {"prfh_i_p_br_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ - {"prfh_i_p_bz_d_64_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ - {"prfh_i_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"prfh_i_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ - {"prfw_i_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ - {"prfw_i_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ - {"prfw_i_p_bi_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ - {"prfw_i_p_br_s"_h, \ - &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ - {"prfw_i_p_bz_d_64_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ - {"prfw_i_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"prfw_i_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets}, \ - {"ptest_p_p"_h, &VISITORCLASS::VisitSVEPredicateTest}, \ + {"rmif_only_rmif"_h, &VISITORCLASS::VisitRotateRightIntoFlags}, \ + {"setf16_only_setf"_h, &VISITORCLASS::VisitEvaluateIntoFlags}, \ + {"setf8_only_setf"_h, &VISITORCLASS::VisitEvaluateIntoFlags}, \ + {"ccmn_32_condcmp_reg"_h, \ + &VISITORCLASS::VisitConditionalCompareRegister}, \ + {"ccmn_64_condcmp_reg"_h, \ + &VISITORCLASS::VisitConditionalCompareRegister}, \ + {"ccmp_32_condcmp_reg"_h, \ + &VISITORCLASS::VisitConditionalCompareRegister}, \ + {"ccmp_64_condcmp_reg"_h, \ + &VISITORCLASS::VisitConditionalCompareRegister}, \ + {"ccmn_32_condcmp_imm"_h, \ + &VISITORCLASS::VisitConditionalCompareImmediate}, \ + {"ccmn_64_condcmp_imm"_h, \ + &VISITORCLASS::VisitConditionalCompareImmediate}, \ + {"ccmp_32_condcmp_imm"_h, \ + &VISITORCLASS::VisitConditionalCompareImmediate}, \ + {"ccmp_64_condcmp_imm"_h, \ + &VISITORCLASS::VisitConditionalCompareImmediate}, \ + {"adrp_only_pcreladdr"_h, &VISITORCLASS::VisitPCRelAddressing}, \ + {"adr_only_pcreladdr"_h, &VISITORCLASS::VisitPCRelAddressing}, \ + {"bl_only_branch_imm"_h, &VISITORCLASS::VisitUnconditionalBranch}, \ + {"b_only_branch_imm"_h, &VISITORCLASS::VisitUnconditionalBranch}, \ + {"autda_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autdb_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autdza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autdzb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autia_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autib_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autiza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"autizb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"cls_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"cls_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"clz_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"clz_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacda_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacdb_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacdza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacdzb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacia_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacib_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"paciza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"pacizb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rbit_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rbit_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rev16_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rev16_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rev32_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rev_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"rev_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"xpacd_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"xpaci_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ + {"cbnz_32_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ + {"cbnz_64_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ + {"cbz_32_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ + {"cbz_64_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ + {"tbnz_only_testbranch"_h, &VISITORCLASS::VisitTestBranch}, \ + {"tbz_only_testbranch"_h, &VISITORCLASS::VisitTestBranch}, \ + {"ldapurb_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapurh_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapursb_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapursb_64_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapursh_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapursh_64_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapursw_64_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapur_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldapur_64_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"stlurb_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"stlurh_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"stlur_32_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"stlur_64_ldapstl_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ + {"ldurb_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldurh_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldursb_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldursb_64_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldursh_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldursh_64_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldursw_64_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_64_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_b_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_d_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_h_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_q_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldur_s_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"prfum_p_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"sturb_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"sturh_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_32_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_64_ldst_unscaled"_h, \ + &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_b_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_d_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_h_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_q_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"stur_s_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ + {"ldrsw_64_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldr_32_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldr_64_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldr_d_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldr_q_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldr_s_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"prfm_p_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ + {"ldnp_32_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"ldnp_64_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"ldnp_d_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"ldnp_q_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"ldnp_s_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"stnp_32_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"stnp_64_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"stnp_d_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"stnp_q_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"stnp_s_ldstnapair_offs"_h, \ + &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ + {"ldraa_64w_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ + {"ldraa_64_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ + {"ldrab_64w_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ + {"ldrab_64_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ + {"fcmpe_dz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmpe_d_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmpe_hz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmpe_h_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmpe_sz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmpe_s_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_dz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_d_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_hz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_h_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_sz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fcmp_s_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ + {"fccmpe_d_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fccmpe_h_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fccmpe_s_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fccmp_d_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fccmp_h_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fccmp_s_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ + {"fcsel_d_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ + {"fcsel_h_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ + {"fcsel_s_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ + {"fadd_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fadd_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fadd_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fdiv_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fdiv_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fdiv_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmaxnm_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmaxnm_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmaxnm_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmax_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmax_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmax_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fminnm_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fminnm_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fminnm_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmin_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmin_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmin_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmul_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmul_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmul_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fnmul_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fnmul_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fnmul_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fsub_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fsub_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fsub_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ + {"fmadd_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fmadd_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fmadd_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fmsub_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fmsub_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fmsub_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmadd_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmadd_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmadd_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmsub_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmsub_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fnmsub_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ + {"fcvtas_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtas_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtas_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtas_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtas_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtas_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtau_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtms_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtmu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtns_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtnu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtps_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtpu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fjcvtzs_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_64vx_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fmov_v64i_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_d32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"scvtf_s64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_d32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"ucvtf_s64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ + {"fcvtzs_32d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzs_32h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzs_32s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzs_64d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzs_64h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzs_64s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_32d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_32h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_32s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_64d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_64h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"fcvtzu_64s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_d32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_d64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_h32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_h64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_s32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"scvtf_s64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_d32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_d64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_h32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_h64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_s32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"ucvtf_s64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ + {"brk_ex_exception"_h, &VISITORCLASS::VisitException}, \ + {"dcps1_dc_exception"_h, &VISITORCLASS::VisitException}, \ + {"dcps2_dc_exception"_h, &VISITORCLASS::VisitException}, \ + {"dcps3_dc_exception"_h, &VISITORCLASS::VisitException}, \ + {"hlt_ex_exception"_h, &VISITORCLASS::VisitException}, \ + {"hvc_ex_exception"_h, &VISITORCLASS::VisitException}, \ + {"smc_ex_exception"_h, &VISITORCLASS::VisitException}, \ + {"svc_ex_exception"_h, &VISITORCLASS::VisitException}, \ + {"sha1h_ss_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ + {"sha1su1_vv_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ + {"sha256su0_vv_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ + {"sha1c_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha1m_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha1p_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha1su0_vvv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha256h2_qqv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha256h_qqv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"sha256su1_vvv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ + {"aesd_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ + {"aese_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ + {"aesimc_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ + {"aesmc_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ + {"sm3partw1_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3partw2_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3ss1_vvv4_crypto4"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3tt1a_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3tt1b_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3tt2a_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm3tt2b_vvv_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ + {"sm4ekey_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitCryptoSM4}, \ + {"sm4e_vv4_cryptosha512_2"_h, &VISITORCLASS::VisitCryptoSM4}, \ + {"fabs_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcmeq_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcmge_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcmgt_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcmle_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcmlt_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtas_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtau_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtms_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtmu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtns_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtnu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtps_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtpu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtzs_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fcvtzu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fneg_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frecpe_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frinta_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frinti_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frintm_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frintn_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frintp_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frintx_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frintz_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"frsqrte_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"fsqrt_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"scvtf_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"ucvtf_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ + {"ld1b_z_p_bi_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1b_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1b_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1b_z_p_bi_u8"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1d_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1h_z_p_bi_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1h_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1h_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sb_z_p_bi_s16"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sb_z_p_bi_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sb_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sh_z_p_bi_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sh_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1sw_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1w_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ + {"ld1w_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousLoad_ScalarPlusImm}, \ {"ptrues_p_s"_h, &VISITORCLASS::VisitSVEPredicateInitialize}, \ {"ptrue_p_s"_h, &VISITORCLASS::VisitSVEPredicateInitialize}, \ - {"punpkhi_p_p"_h, &VISITORCLASS::VisitSVEUnpackPredicateElements}, \ - {"punpklo_p_p"_h, &VISITORCLASS::VisitSVEUnpackPredicateElements}, \ - {"rbit_z_p_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ - {"rdffrs_p_p_f"_h, \ - &VISITORCLASS::VisitSVEPredicateReadFromFFR_Predicated}, \ - {"rdffr_p_f"_h, \ - &VISITORCLASS::VisitSVEPredicateReadFromFFR_Unpredicated}, \ - {"rdffr_p_p_f"_h, \ - &VISITORCLASS::VisitSVEPredicateReadFromFFR_Predicated}, \ - {"rdvl_r_i"_h, &VISITORCLASS::VisitSVEStackFrameSize}, \ - {"revb_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ - {"revh_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ - {"revw_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ - {"rev_p_p"_h, &VISITORCLASS::VisitSVEReversePredicateElements}, \ - {"rev_z_z"_h, &VISITORCLASS::VisitSVEReverseVectorElements}, \ - {"sabd_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"saddv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"scvtf_z_p_z_h2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_w2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_w2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_w2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_x2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_x2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"scvtf_z_p_z_x2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"sdivr_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ - {"sdiv_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ - {"sdot_z_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddUnpredicated}, \ - {"sdot_z_zzzi_d"_h, &VISITORCLASS::VisitSVEMulIndex}, \ - {"sdot_z_zzzi_s"_h, &VISITORCLASS::VisitSVEMulIndex}, \ - {"sel_p_p_pp"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ - {"sel_z_p_zz"_h, &VISITORCLASS::VisitSVEVectorSelect}, \ - {"setffr_f"_h, &VISITORCLASS::VisitSVEFFRInitialise}, \ - {"smaxv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"smax_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"smax_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ - {"sminv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"smin_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"smin_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ - {"smulh_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ - {"splice_z_p_zz_des"_h, &VISITORCLASS::VisitSVEVectorSplice}, \ + {"index_z_ii"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ + {"index_z_ir"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ + {"index_z_ri"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ + {"index_z_rr"_h, &VISITORCLASS::VisitSVEIndexGeneration}, \ + {"adr_z_az_d_s32_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ + {"adr_z_az_d_u32_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ + {"adr_z_az_sd_same_scaled"_h, &VISITORCLASS::VisitSVEAddressGeneration}, \ + {"ld1rqb_z_p_bi_u8"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ + {"ld1rqd_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ + {"ld1rqh_z_p_bi_u16"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ + {"ld1rqw_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, \ + {"add_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ {"sqadd_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"sqadd_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"sqdecb_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecb_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecd_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecd_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecd_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"sqdech_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdech_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdech_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"sqdecp_r_p_r_sx"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqdecp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqdecp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqdecw_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecw_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqdecw_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"sqincb_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincb_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincd_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincd_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincd_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"sqinch_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqinch_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqinch_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"sqincp_r_p_r_sx"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqincp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqincp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"sqincw_r_rs_sx"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincw_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"sqincw_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ {"sqsub_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"sqsub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"st1b_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ - {"st1b_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ - {"st1b_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ - {"st1b_z_p_br"_h, \ - &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ - {"st1b_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ - {"st1b_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"st1b_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ - {"st1d_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ - {"st1d_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ - {"st1d_z_p_br"_h, \ - &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ - {"st1d_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ - {"st1d_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ - {"st1d_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"st1d_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"st1h_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ - {"st1h_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ - {"st1h_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ - {"st1h_z_p_br"_h, \ - &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ - {"st1h_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ - {"st1h_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ - {"st1h_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"st1h_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"st1h_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets}, \ - {"st1h_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ - {"st1w_z_p_ai_d"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ - {"st1w_z_p_ai_s"_h, \ - &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ - {"st1w_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ - {"st1w_z_p_br"_h, \ - &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusScalar}, \ - {"st1w_z_p_bz_d_64_scaled"_h, \ - &VISITORCLASS::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets}, \ - {"st1w_z_p_bz_d_64_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets}, \ - {"st1w_z_p_bz_d_x32_scaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets}, \ - {"st1w_z_p_bz_d_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets}, \ - {"st1w_z_p_bz_s_x32_scaled"_h, \ - &VISITORCLASS::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets}, \ - {"st1w_z_p_bz_s_x32_unscaled"_h, \ - &VISITORCLASS:: \ - VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets}, \ - {"st2b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st2b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st2d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st2d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st2h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st2h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st2w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st2w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st3b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st3b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st3d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st3d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st3h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st3h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st3w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st3w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st4b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st4b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st4d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st4d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st4h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st4h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"st4w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusImm}, \ - {"st4w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEStoreMultipleStructures_ScalarPlusScalar}, \ - {"stnt1b_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ - {"stnt1b_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ - {"stnt1d_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ - {"stnt1d_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ - {"stnt1h_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ - {"stnt1h_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ - {"stnt1w_z_p_bi_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ - {"stnt1w_z_p_br_contiguous"_h, \ - &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar}, \ - {"str_p_bi"_h, &VISITORCLASS::VisitSVEStorePredicateRegister}, \ - {"str_z_bi"_h, &VISITORCLASS::VisitSVEStoreVectorRegister}, \ - {"subr_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ {"subr_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"sub_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntAddSubtractVectors_Predicated}, \ {"sub_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"sub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"sunpkhi_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ - {"sunpklo_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ - {"sxtb_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"sxth_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"sxtw_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"tbl_z_zz_1"_h, &VISITORCLASS::VisitSVETableLookup}, \ - {"trn1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"trn1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ - {"trn2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"trn2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ - {"uabd_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"uaddv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"ucvtf_z_p_z_h2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_w2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_w2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_w2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_x2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_x2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"ucvtf_z_p_z_x2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ - {"udf_only_perm_undef"_h, &VISITORCLASS::VisitReserved}, \ - {"udivr_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ - {"udiv_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ - {"udot_z_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddUnpredicated}, \ - {"udot_z_zzzi_d"_h, &VISITORCLASS::VisitSVEMulIndex}, \ - {"udot_z_zzzi_s"_h, &VISITORCLASS::VisitSVEMulIndex}, \ - {"umaxv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"umax_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"umax_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ - {"uminv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ - {"umin_z_p_zz"_h, \ - &VISITORCLASS::VisitSVEIntMinMaxDifference_Predicated}, \ - {"umin_z_zi"_h, &VISITORCLASS::VisitSVEIntMinMaxImm_Unpredicated}, \ - {"umulh_z_p_zz"_h, &VISITORCLASS::VisitSVEIntMulVectors_Predicated}, \ {"uqadd_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"uqadd_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"uqdecb_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecb_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecd_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecd_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecd_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"uqdech_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdech_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdech_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"uqdecp_r_p_r_uw"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqdecp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqdecp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqdecw_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecw_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqdecw_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"uqincb_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincb_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincd_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincd_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincd_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"uqinch_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqinch_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqinch_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ - {"uqincp_r_p_r_uw"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqincp_r_p_r_x"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqincp_z_p_z"_h, &VISITORCLASS::VisitSVEIncDecByPredicateCount}, \ - {"uqincw_r_rs_uw"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincw_r_rs_x"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ - {"uqincw_z_zs"_h, \ - &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ {"uqsub_z_zi"_h, &VISITORCLASS::VisitSVEIntAddSubtractImm_Unpredicated}, \ - {"uqsub_z_zz"_h, &VISITORCLASS::VisitSVEIntArithmeticUnpredicated}, \ - {"uunpkhi_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ - {"uunpklo_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ - {"uxtb_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"uxth_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"uxtw_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ - {"uzp1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"uzp1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ - {"uzp2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"uzp2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ {"whilele_p_p_rr"_h, \ &VISITORCLASS::VisitSVEIntCompareScalarCountAndLimit}, \ {"whilelo_p_p_rr"_h, \ @@ -1191,27 +1307,678 @@ &VISITORCLASS::VisitSVEIntCompareScalarCountAndLimit}, \ {"whilelt_p_p_rr"_h, \ &VISITORCLASS::VisitSVEIntCompareScalarCountAndLimit}, \ - {"wrffr_f_p"_h, &VISITORCLASS::VisitSVEFFRWriteFromPredicate}, \ - {"zip1_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"zip1_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ - {"zip2_p_pp"_h, &VISITORCLASS::VisitSVEPermutePredicateElements}, \ - {"zip2_z_zz"_h, &VISITORCLASS::VisitSVEPermuteVectorInterleaving}, \ - {"adds_32s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"adds_64s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"add_32_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"add_64_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"subs_32s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"subs_64s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"sub_32_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"sub_64_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ - {"adds_32s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"adds_64s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"add_32_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"add_64_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"subs_32s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"subs_64s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"sub_32_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ - {"sub_64_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"ptrues_p_s"_h, &VISITORCLASS::VisitSVEPredicateInitialize}, \ + {"ptrue_p_s"_h, &VISITORCLASS::VisitSVEPredicateInitialize}, \ + {"fmov_d_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ + {"fmov_h_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ + {"fmov_s_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ + {"fabs_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fabs_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fabs_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fneg_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fneg_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fneg_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fsqrt_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fsqrt_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"fsqrt_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ + {"bic_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"bic_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"fmov_asimdimm_d2_d"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"fmov_asimdimm_h_h"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"fmov_asimdimm_s_s"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_d2_d"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_d_ds"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_m_sm"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"movi_asimdimm_n_b"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"mvni_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"mvni_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"mvni_asimdimm_m_sm"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"orr_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"orr_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ + {"tbl_asimdtbl_l1_1"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbl_asimdtbl_l2_2"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbl_asimdtbl_l3_3"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbl_asimdtbl_l4_4"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbx_asimdtbl_l1_1"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbx_asimdtbl_l2_2"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbx_asimdtbl_l3_3"_h, &VISITORCLASS::VisitNEONTable}, \ + {"tbx_asimdtbl_l4_4"_h, &VISITORCLASS::VisitNEONTable}, \ + {"andv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"eorv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"orv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"saddv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"smaxv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"sminv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"uaddv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"umaxv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"uminv_r_p_z"_h, &VISITORCLASS::VisitSVEIntReduction}, \ + {"sdot_z_zzzi_d"_h, &VISITORCLASS::VisitSVEMulIndex}, \ + {"sdot_z_zzzi_s"_h, &VISITORCLASS::VisitSVEMulIndex}, \ + {"udot_z_zzzi_d"_h, &VISITORCLASS::VisitSVEMulIndex}, \ + {"udot_z_zzzi_s"_h, &VISITORCLASS::VisitSVEMulIndex}, \ + {"fabd_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"facge_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"facgt_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"faddp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fadd_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fcmeq_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fcmge_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fcmgt_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fdiv_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmaxnmp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmaxnm_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmaxp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmax_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fminnmp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fminnm_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fminp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmin_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmla_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmls_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmulx_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fmul_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"frecps_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"frsqrts_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"fsub_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ + {"ld1r_asisdlso_r1"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld2r_asisdlso_r2"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld3r_asisdlso_r3"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld4r_asisdlso_r4"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld1r_asisdlsop_r1_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1r_asisdlsop_rx1_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2r_asisdlsop_r2_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2r_asisdlsop_rx2_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3r_asisdlsop_r3_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3r_asisdlsop_rx3_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4r_asisdlsop_r4_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4r_asisdlsop_rx4_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlso_b1_1b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld2_asisdlso_b2_2b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld3_asisdlso_b3_3b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld4_asisdlso_b4_4b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st1_asisdlso_b1_1b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st2_asisdlso_b2_2b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st3_asisdlso_b3_3b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st4_asisdlso_b4_4b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld1_asisdlsop_b1_i1b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlsop_bx1_r1b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_b2_i2b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_bx2_r2b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_b3_i3b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_bx3_r3b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_b4_i4b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_bx4_r4b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_b1_i1b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_bx1_r1b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_b2_i2b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_bx2_r2b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_b3_i3b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_bx3_r3b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_b4_i4b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_bx4_r4b"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlso_h1_1h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld2_asisdlso_h2_2h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld3_asisdlso_h3_3h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld4_asisdlso_h4_4h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st1_asisdlso_h1_1h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st2_asisdlso_h2_2h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st3_asisdlso_h3_3h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st4_asisdlso_h4_4h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld1_asisdlsop_h1_i1h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlsop_hx1_r1h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_h2_i2h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_hx2_r2h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_h3_i3h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_hx3_r3h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_h4_i4h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_hx4_r4h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_h1_i1h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_hx1_r1h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_h2_i2h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_hx2_r2h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_h3_i3h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_hx3_r3h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_h4_i4h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_hx4_r4h"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlso_s1_1s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld2_asisdlso_s2_2s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld3_asisdlso_s3_3s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld4_asisdlso_s4_4s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st1_asisdlso_s1_1s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st2_asisdlso_s2_2s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st3_asisdlso_s3_3s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st4_asisdlso_s4_4s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld1_asisdlsop_s1_i1s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlsop_sx1_r1s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_s2_i2s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_sx2_r2s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_s3_i3s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_sx3_r3s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_s4_i4s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_sx4_r4s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_s1_i1s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_sx1_r1s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_s2_i2s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_sx2_r2s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_s3_i3s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_sx3_r3s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_s4_i4s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_sx4_r4s"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlso_d1_1d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld2_asisdlso_d2_2d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld3_asisdlso_d3_3d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld4_asisdlso_d4_4d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st1_asisdlso_d1_1d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st2_asisdlso_d2_2d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st3_asisdlso_d3_3d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"st4_asisdlso_d4_4d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ + {"ld1_asisdlsop_d1_i1d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlsop_dx1_r1d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_d2_i2d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld2_asisdlsop_dx2_r2d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_d3_i3d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld3_asisdlsop_dx3_r3d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_d4_i4d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld4_asisdlsop_dx4_r4d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_d1_i1d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st1_asisdlsop_dx1_r1d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_d2_i2d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st2_asisdlsop_dx2_r2d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_d3_i3d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st3_asisdlsop_dx3_r3d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_d4_i4d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"st4_asisdlsop_dx4_r4d"_h, \ + &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ + {"ld1_asisdlsep_i1_i1"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_i2_i2"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_i3_i3"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_i4_i4"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_r1_r1"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_r2_r2"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_r3_r3"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld1_asisdlsep_r4_r4"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld2_asisdlsep_i2_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld2_asisdlsep_r2_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld3_asisdlsep_i3_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld3_asisdlsep_r3_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld4_asisdlsep_i4_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ld4_asisdlsep_r4_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_i1_i1"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_i2_i2"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_i3_i3"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_i4_i4"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_r1_r1"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_r2_r2"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_r3_r3"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st1_asisdlsep_r4_r4"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st2_asisdlsep_i2_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st2_asisdlsep_r2_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st3_asisdlsep_i3_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st3_asisdlsep_r3_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st4_asisdlsep_i4_i"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"st4_asisdlsep_r4_r"_h, \ + &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ + {"ldrb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrsb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrsb_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrsh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrsh_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrsw_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_b_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_d_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_h_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_q_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldr_s_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"strb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"strh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_b_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_d_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_h_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_q_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"str_s_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ + {"ldrb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrsb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrsb_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrsh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrsh_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrsw_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_b_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_d_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_h_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_q_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldr_s_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"strb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"strh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_b_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_d_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_h_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_q_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"str_s_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ + {"ldrb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrsb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrsb_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrsh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrsh_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrsw_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_b_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_d_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_h_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_q_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldr_s_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"prfm_p_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"strb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"strh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_b_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_d_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_h_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_q_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"str_s_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ + {"ldrb_32bl_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrb_32b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsb_32bl_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsb_32b_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsb_64bl_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsb_64b_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsh_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldrsw_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_bl_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_d_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_h_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_q_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldr_s_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"prfm_p_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"strb_32bl_ldst_regoff"_h, \ + &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"strb_32b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"strh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_bl_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_d_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_h_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_q_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"str_s_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ + {"ldpsw_64_ldstpair_post"_h, \ + &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldp_32_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldp_64_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldp_d_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldp_q_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldp_s_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"stp_32_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"stp_64_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"stp_d_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"stp_q_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"stp_s_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ + {"ldpsw_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldp_32_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldp_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldp_d_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldp_q_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldp_s_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"stp_32_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"stp_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"stp_d_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"stp_q_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"stp_s_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ + {"ldpsw_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"ldp_32_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"ldp_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"ldp_d_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"ldp_q_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"ldp_s_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"stp_32_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"stp_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"stp_d_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"stp_q_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"stp_s_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ + {"addp_asisdpair_only"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"faddp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"faddp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fmaxnmp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fmaxnmp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fmaxp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fmaxp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fminnmp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fminnmp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fminp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"fminp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ + {"asr_z_p_zw"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ + {"lsl_z_p_zw"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ + {"lsr_z_p_zw"_h, \ + &VISITORCLASS::VisitSVEBitwiseShiftByWideElements_Predicated}, \ + {"frinta_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frinti_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frintm_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frintn_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frintp_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frintx_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frintz_z_p_z"_h, &VISITORCLASS::VisitSVEFPRoundToIntegralValue}, \ + {"frecpx_z_p_z"_h, &VISITORCLASS::VisitSVEFPUnaryOp}, \ + {"fsqrt_z_p_z"_h, &VISITORCLASS::VisitSVEFPUnaryOp}, \ + {"frecpe_z_z"_h, &VISITORCLASS::VisitSVEFPUnaryOpUnpredicated}, \ + {"frsqrte_z_z"_h, &VISITORCLASS::VisitSVEFPUnaryOpUnpredicated}, \ + {"fmad_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fmls_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fmsb_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fnmad_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fnmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fnmls_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"fnmsb_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPMulAdd}, \ + {"faddv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ + {"fmaxnmv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ + {"fmaxv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ + {"fminnmv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ + {"fminv_v_p_z"_h, &VISITORCLASS::VisitSVEFPFastReduction}, \ + {"fcmla_z_p_zzz"_h, &VISITORCLASS::VisitSVEFPComplexMulAdd}, \ + {"fcadd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPComplexAddition}, \ + {"fcmeq_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"fcmge_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"fcmgt_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"fcmle_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"fcmlt_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"fcmne_p_p_z0"_h, &VISITORCLASS::VisitSVEFPCompareWithZero}, \ + {"facge_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"facgt_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fcmeq_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fcmge_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fcmgt_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fcmne_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fcmuo_p_p_zz"_h, &VISITORCLASS::VisitSVEFPCompareVectors}, \ + {"fadd_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"fmul_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"frecps_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"frsqrts_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"fsub_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"ftsmul_z_zz"_h, &VISITORCLASS::VisitSVEFPArithmeticUnpredicated}, \ + {"fadda_v_p_z"_h, &VISITORCLASS::VisitSVEFPAccumulatingReduction}, \ + {"abs_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"cls_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"clz_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"cnot_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"cnt_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"fabs_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"fneg_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"neg_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"not_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"sxtb_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"sxth_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"sxtw_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"uxtb_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"uxth_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"uxtw_z_p_z"_h, &VISITORCLASS::VisitSVEIntUnaryArithmeticPredicated}, \ + {"asr_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"asr_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"lsl_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"lsl_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"lsr_z_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"lsr_z_zw"_h, &VISITORCLASS::VisitSVEBitwiseShiftUnpredicated}, \ + {"sunpkhi_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ + {"sunpklo_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ + {"uunpkhi_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ + {"uunpklo_z_z"_h, &VISITORCLASS::VisitSVEUnpackVectorElements}, \ + {"and_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ + {"bic_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ + {"eor_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ + {"orr_z_zz"_h, &VISITORCLASS::VisitSVEBitwiseLogicalUnpredicated}, \ + {"scvtf_z_p_z_h2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_w2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_w2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_w2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_x2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_x2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"scvtf_z_p_z_x2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_h2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_w2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_w2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_w2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_x2d"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_x2fp16"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"ucvtf_z_p_z_x2s"_h, &VISITORCLASS::VisitSVEIntConvertToFP}, \ + {"rbit_z_p_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ + {"revb_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ + {"revh_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ + {"revw_z_z"_h, &VISITORCLASS::VisitSVEReverseWithinElements}, \ + {"rev_p_p"_h, &VISITORCLASS::VisitSVEReversePredicateElements}, \ + {"rev_z_z"_h, &VISITORCLASS::VisitSVEReverseVectorElements}, \ + {"insr_z_r"_h, &VISITORCLASS::VisitSVEInsertGeneralRegister}, \ + {"ftssel_z_zz"_h, &VISITORCLASS::VisitSVEFPTrigSelectCoefficient}, \ + {"ftmad_z_zzi"_h, &VISITORCLASS::VisitSVEFPTrigMulAddCoefficient}, \ + {"fexpa_z_z"_h, &VISITORCLASS::VisitSVEFPExponentialAccelerator}, \ + {"fabd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fadd_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fdivr_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fdiv_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fmaxnm_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fmax_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fminnm_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fmin_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fmulx_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fmul_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fscale_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fsubr_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fsub_z_p_zz"_h, &VISITORCLASS::VisitSVEFPArithmetic_Predicated}, \ + {"fadd_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fmaxnm_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fmax_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fminnm_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fmin_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fmul_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fsubr_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"fsub_z_p_zs"_h, \ + &VISITORCLASS::VisitSVEFPArithmeticWithImm_Predicated}, \ + {"and_z_zi"_h, \ + &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ + {"eor_z_zi"_h, \ + &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ + {"orr_z_zi"_h, \ + &VISITORCLASS::VisitSVEBitwiseLogicalWithImm_Unpredicated}, \ + {"blraaz_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"blraa_64p_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"blrabz_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"blrab_64p_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"blr_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"braaz_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"braa_64p_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"brabz_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"brab_64p_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"br_64_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"drps_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"eretaa_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"eretab_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"eret_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"retaa_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"retab_64e_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"ret_64r_branch_reg"_h, \ + &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ + {"ext_asimdext_only"_h, &VISITORCLASS::VisitNEONExtract}, \ + {"rbit_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cnt_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"rev16_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"fmla_asisdelem_rh_h"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmla_asisdelem_r_sd"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmls_asisdelem_rh_h"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmls_asisdelem_r_sd"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmulx_asisdelem_rh_h"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmulx_asisdelem_r_sd"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmul_asisdelem_rh_h"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"fmul_asisdelem_r_sd"_h, \ + &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ + {"csel_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csel_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csinc_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csinc_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csinv_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csinv_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csneg_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"csneg_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ + {"ands_32s_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"ands_64s_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"and_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"and_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"eor_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"eor_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"orr_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ + {"orr_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ {"adds_32_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ {"adds_64_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ {"add_32_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ @@ -1220,14 +1987,79 @@ {"subs_64_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ {"sub_32_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ {"sub_64_addsub_shift"_h, &VISITORCLASS::VisitAddSubShifted}, \ - {"adcs_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"adcs_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"adc_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"adc_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"sbcs_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"sbcs_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"sbc_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ - {"sbc_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"adds_32s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"adds_64s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"add_32_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"add_64_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"subs_32s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"subs_64s_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"sub_32_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"sub_64_addsub_imm"_h, &VISITORCLASS::VisitAddSubImmediate}, \ + {"adds_32s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"adds_64s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"add_32_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"add_64_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"subs_32s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"subs_64s_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"sub_32_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"sub_64_addsub_ext"_h, &VISITORCLASS::VisitAddSubExtended}, \ + {"ands_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"ands_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"and_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"and_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"bics_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"bics_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"bic_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"bic_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"eon_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"eon_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"eor_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"eor_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"orn_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"orn_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"orr_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"orr_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ + {"extr_32_extract"_h, &VISITORCLASS::VisitExtract}, \ + {"extr_64_extract"_h, &VISITORCLASS::VisitExtract}, \ + {"asrv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"asrv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32b_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32cb_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32ch_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32cw_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32cx_64c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32h_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32w_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"crc32x_64c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"lslv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"lslv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"lsrv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"lsrv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"pacga_64p_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"rorv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"rorv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"sdiv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"sdiv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"udiv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"udiv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ + {"madd_32a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"madd_64a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"msub_32a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"msub_64a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"smaddl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"smsubl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"smulh_64_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"umaddl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"umsubl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"umulh_64_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ + {"b_only_condbranch"_h, &VISITORCLASS::VisitConditionalBranch}, \ + {"bc_only_condbranch"_h, &VISITORCLASS::VisitConditionalBranch}, \ + {"bfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ + {"bfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ + {"sbfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ + {"sbfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ + {"ubfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ + {"ubfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ {"ldaddab_32_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ {"ldaddah_32_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ {"ldaddalb_32_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ @@ -1376,728 +2208,253 @@ {"swpl_64_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ {"swp_32_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ {"swp_64_memop"_h, &VISITORCLASS::VisitAtomicMemory}, \ - {"bfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"bfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"sbfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"sbfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"ubfm_32m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"ubfm_64m_bitfield"_h, &VISITORCLASS::VisitBitfield}, \ - {"cbnz_32_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ - {"cbnz_64_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ - {"cbz_32_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ - {"cbz_64_compbranch"_h, &VISITORCLASS::VisitCompareBranch}, \ - {"b_only_condbranch"_h, &VISITORCLASS::VisitConditionalBranch}, \ - {"ccmn_32_condcmp_imm"_h, \ - &VISITORCLASS::VisitConditionalCompareImmediate}, \ - {"ccmn_64_condcmp_imm"_h, \ - &VISITORCLASS::VisitConditionalCompareImmediate}, \ - {"ccmp_32_condcmp_imm"_h, \ - &VISITORCLASS::VisitConditionalCompareImmediate}, \ - {"ccmp_64_condcmp_imm"_h, \ - &VISITORCLASS::VisitConditionalCompareImmediate}, \ - {"ccmn_32_condcmp_reg"_h, \ - &VISITORCLASS::VisitConditionalCompareRegister}, \ - {"ccmn_64_condcmp_reg"_h, \ - &VISITORCLASS::VisitConditionalCompareRegister}, \ - {"ccmp_32_condcmp_reg"_h, \ - &VISITORCLASS::VisitConditionalCompareRegister}, \ - {"ccmp_64_condcmp_reg"_h, \ - &VISITORCLASS::VisitConditionalCompareRegister}, \ - {"csel_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csel_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csinc_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csinc_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csinv_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csinv_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csneg_32_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"csneg_64_condsel"_h, &VISITORCLASS::VisitConditionalSelect}, \ - {"sha1h_ss_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ - {"sha1su1_vv_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ - {"sha256su0_vv_cryptosha2"_h, &VISITORCLASS::VisitCrypto2RegSHA}, \ - {"sha1c_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha1m_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha1p_qsv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha1su0_vvv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha256h2_qqv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha256h_qqv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"sha256su1_vvv_cryptosha3"_h, &VISITORCLASS::VisitCrypto3RegSHA}, \ - {"aesd_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ - {"aese_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ - {"aesimc_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ - {"aesmc_b_cryptoaes"_h, &VISITORCLASS::VisitCryptoAES}, \ - {"autda_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autdb_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autdza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autdzb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autia_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autib_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autiza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"autizb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"cls_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"cls_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"clz_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"clz_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacda_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacdb_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacdza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacdzb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacia_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacib_64p_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"paciza_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"pacizb_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rbit_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rbit_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rev16_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rev16_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rev32_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rev_32_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"rev_64_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"xpacd_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"xpaci_64z_dp_1src"_h, &VISITORCLASS::VisitDataProcessing1Source}, \ - {"asrv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"asrv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32b_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32cb_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32ch_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32cw_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32cx_64c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32h_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32w_32c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"crc32x_64c_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"lslv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"lslv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"lsrv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"lsrv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"pacga_64p_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"rorv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"rorv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"sdiv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"sdiv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"udiv_32_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"udiv_64_dp_2src"_h, &VISITORCLASS::VisitDataProcessing2Source}, \ - {"madd_32a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"madd_64a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"msub_32a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"msub_64a_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"smaddl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"smsubl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"smulh_64_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"umaddl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"umsubl_64wa_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"umulh_64_dp_3src"_h, &VISITORCLASS::VisitDataProcessing3Source}, \ - {"setf16_only_setf"_h, &VISITORCLASS::VisitEvaluateIntoFlags}, \ - {"setf8_only_setf"_h, &VISITORCLASS::VisitEvaluateIntoFlags}, \ - {"brk_ex_exception"_h, &VISITORCLASS::VisitException}, \ - {"dcps1_dc_exception"_h, &VISITORCLASS::VisitException}, \ - {"dcps2_dc_exception"_h, &VISITORCLASS::VisitException}, \ - {"dcps3_dc_exception"_h, &VISITORCLASS::VisitException}, \ - {"hlt_ex_exception"_h, &VISITORCLASS::VisitException}, \ - {"hvc_ex_exception"_h, &VISITORCLASS::VisitException}, \ - {"smc_ex_exception"_h, &VISITORCLASS::VisitException}, \ - {"svc_ex_exception"_h, &VISITORCLASS::VisitException}, \ - {"extr_32_extract"_h, &VISITORCLASS::VisitExtract}, \ - {"extr_64_extract"_h, &VISITORCLASS::VisitExtract}, \ - {"fcmpe_dz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmpe_d_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmpe_hz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmpe_h_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmpe_sz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmpe_s_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_dz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_d_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_hz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_h_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_sz_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fcmp_s_floatcmp"_h, &VISITORCLASS::VisitFPCompare}, \ - {"fccmpe_d_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fccmpe_h_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fccmpe_s_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fccmp_d_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fccmp_h_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fccmp_s_floatccmp"_h, &VISITORCLASS::VisitFPConditionalCompare}, \ - {"fcsel_d_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ - {"fcsel_h_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ - {"fcsel_s_floatsel"_h, &VISITORCLASS::VisitFPConditionalSelect}, \ - {"bfcvt_bs_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fabs_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fabs_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fabs_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_dh_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_ds_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_hd_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_hs_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_sd_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fcvt_sh_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fmov_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fmov_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fmov_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fneg_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fneg_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fneg_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint32x_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint32x_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint32z_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint32z_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint64x_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint64x_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint64z_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frint64z_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinta_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinta_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinta_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinti_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinti_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frinti_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintm_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintm_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintm_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintn_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintn_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintn_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintp_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintp_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintp_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintx_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintx_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintx_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintz_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintz_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"frintz_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fsqrt_d_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fsqrt_h_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fsqrt_s_floatdp1"_h, &VISITORCLASS::VisitFPDataProcessing1Source}, \ - {"fadd_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fadd_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fadd_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fdiv_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fdiv_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fdiv_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmaxnm_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmaxnm_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmaxnm_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmax_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmax_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmax_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fminnm_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fminnm_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fminnm_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmin_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmin_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmin_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmul_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmul_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmul_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fnmul_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fnmul_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fnmul_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fsub_d_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fsub_h_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fsub_s_floatdp2"_h, &VISITORCLASS::VisitFPDataProcessing2Source}, \ - {"fmadd_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fmadd_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fmadd_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fmsub_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fmsub_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fmsub_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmadd_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmadd_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmadd_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmsub_d_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmsub_h_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fnmsub_s_floatdp3"_h, &VISITORCLASS::VisitFPDataProcessing3Source}, \ - {"fcvtzs_32d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzs_32h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzs_32s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzs_64d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzs_64h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzs_64s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_32d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_32h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_32s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_64d_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_64h_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fcvtzu_64s_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_d32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_d64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_h32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_h64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_s32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"scvtf_s64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_d32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_d64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_h32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_h64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_s32_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"ucvtf_s64_float2fix"_h, &VISITORCLASS::VisitFPFixedPointConvert}, \ - {"fmov_d_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ - {"fmov_h_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ - {"fmov_s_floatimm"_h, &VISITORCLASS::VisitFPImmediate}, \ - {"fcvtas_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtas_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtas_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtas_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtas_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtas_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtau_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtms_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtmu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtns_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtnu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtps_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtpu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzs_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fcvtzu_64s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fjcvtzs_32d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_32h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_32s_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_64d_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_64h_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_64vx_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"fmov_v64i_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_d32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"scvtf_s64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_d32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_d64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_h32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_h64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_s32_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ucvtf_s64_float2int"_h, &VISITORCLASS::VisitFPIntegerConvert}, \ - {"ldrsw_64_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"ldr_32_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"ldr_64_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"ldr_d_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"ldr_q_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"ldr_s_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"prfm_p_loadlit"_h, &VISITORCLASS::VisitLoadLiteral}, \ - {"casab_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casah_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casalb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casalh_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casal_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casal_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casa_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casa_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"cash_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caslb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caslh_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casl_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casl_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspal_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspal_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspa_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspa_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspl_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"caspl_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casp_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"casp_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"cas_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"cas_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldarb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldarh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldar_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldar_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxp_lp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxp_lp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxrb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxrh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxr_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldaxr_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldlarb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldlarh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldlar_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldlar_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxp_lp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxp_lp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxrb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxrh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxr_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldxr_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stllrb_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stllrh_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stllr_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stllr_sl64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlrb_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlrh_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlr_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlr_sl64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxp_sp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxp_sp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxrb_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxrh_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxr_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stlxr_sr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxp_sp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxp_sp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxrb_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxrh_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxr_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"stxr_sr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ - {"ldraa_64w_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ - {"ldraa_64_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ - {"ldrab_64w_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ - {"ldrab_64_ldst_pac"_h, &VISITORCLASS::VisitLoadStorePAC}, \ - {"ldnp_32_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"ldnp_64_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"ldnp_d_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"ldnp_q_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"ldnp_s_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"stnp_32_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"stnp_64_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"stnp_d_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"stnp_q_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"stnp_s_ldstnapair_offs"_h, \ - &VISITORCLASS::VisitLoadStorePairNonTemporal}, \ - {"ldpsw_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldp_32_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldp_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldp_d_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldp_q_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldp_s_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"stp_32_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"stp_64_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"stp_d_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"stp_q_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"stp_s_ldstpair_off"_h, &VISITORCLASS::VisitLoadStorePairOffset}, \ - {"ldpsw_64_ldstpair_post"_h, \ - &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldp_32_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldp_64_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldp_d_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldp_q_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldp_s_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"stp_32_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"stp_64_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"stp_d_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"stp_q_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"stp_s_ldstpair_post"_h, &VISITORCLASS::VisitLoadStorePairPostIndex}, \ - {"ldpsw_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldp_32_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldp_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldp_d_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldp_q_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldp_s_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"stp_32_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"stp_64_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"stp_d_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"stp_q_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"stp_s_ldstpair_pre"_h, &VISITORCLASS::VisitLoadStorePairPreIndex}, \ - {"ldrb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrsb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrsb_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrsh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrsh_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrsw_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_b_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_d_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_h_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_q_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldr_s_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"strb_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"strh_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_32_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_64_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_b_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_d_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_h_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_q_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"str_s_ldst_immpost"_h, &VISITORCLASS::VisitLoadStorePostIndex}, \ - {"ldrb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrsb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrsb_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrsh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrsh_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldrsw_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_b_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_d_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_h_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_q_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldr_s_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"strb_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"strh_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_32_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_64_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_b_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_d_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_h_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_q_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"str_s_ldst_immpre"_h, &VISITORCLASS::VisitLoadStorePreIndex}, \ - {"ldapurb_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapurh_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapursb_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapursb_64_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapursh_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapursh_64_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapursw_64_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapur_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldapur_64_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"stlurb_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"stlurh_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"stlur_32_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"stlur_64_ldapstl_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreRCpcUnscaledOffset}, \ - {"ldrb_32bl_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrb_32b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsb_32bl_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsb_32b_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsb_64bl_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsb_64b_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsh_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldrsw_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_bl_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_d_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_h_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_q_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldr_s_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"prfm_p_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"strb_32bl_ldst_regoff"_h, \ - &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"strb_32b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"strh_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_32_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_64_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_bl_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_b_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_d_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_h_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_q_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"str_s_ldst_regoff"_h, &VISITORCLASS::VisitLoadStoreRegisterOffset}, \ - {"ldurb_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldurh_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldursb_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldursb_64_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldursh_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldursh_64_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldursw_64_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_64_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_b_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_d_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_h_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_q_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldur_s_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"prfum_p_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"sturb_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"sturh_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_32_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_64_ldst_unscaled"_h, \ - &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_b_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_d_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_h_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_q_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"stur_s_ldst_unscaled"_h, &VISITORCLASS::VisitLoadStoreUnscaledOffset}, \ - {"ldrb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrsb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrsb_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrsh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrsh_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldrsw_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_b_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_d_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_h_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_q_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ldr_s_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"prfm_p_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"strb_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"strh_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_32_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_64_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_b_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_d_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_h_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_q_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"str_s_ldst_pos"_h, &VISITORCLASS::VisitLoadStoreUnsignedOffset}, \ - {"ands_32s_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"ands_64s_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"and_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"and_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"eor_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"eor_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"orr_32_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"orr_64_log_imm"_h, &VISITORCLASS::VisitLogicalImmediate}, \ - {"ands_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"ands_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"and_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"and_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"bics_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"bics_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"bic_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"bic_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"eon_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"eon_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"eor_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"eor_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"orn_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"orn_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"orr_32_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"orr_64_log_shift"_h, &VISITORCLASS::VisitLogicalShifted}, \ - {"movk_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"movk_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"movn_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"movn_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"movz_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"movz_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ - {"fabs_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcmeq_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcmge_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcmgt_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcmle_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcmlt_asimdmiscfp16_fz"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtas_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtau_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtms_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtmu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtns_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtnu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtps_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtpu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtzs_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fcvtzu_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fneg_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frecpe_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frinta_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frinti_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frintm_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frintn_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frintp_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frintx_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frintz_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"frsqrte_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"fsqrt_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"scvtf_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"ucvtf_asimdmiscfp16_r"_h, &VISITORCLASS::VisitNEON2RegMiscFP16}, \ - {"addhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"raddhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"rsubhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"sabal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"sabdl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"saddl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"saddw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"smlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"smlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"smull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"sqdmlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"sqdmlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"sqdmull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"ssubl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"ssubw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"subhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"uabal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"uabdl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"uaddl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"uaddw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"umlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"umlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"umull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"usubl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"usubw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"sel_z_p_zz"_h, &VISITORCLASS::VisitSVEVectorSelect}, \ + {"ands_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"and_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"bics_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"bic_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"eors_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"eor_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"nands_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"nand_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"nors_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"nor_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"orns_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"orn_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"orrs_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"orr_p_p_pp_z"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"sel_p_p_pp"_h, &VISITORCLASS::VisitSVEPredicateLogical}, \ + {"sdivr_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ + {"sdiv_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ + {"udivr_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ + {"udiv_z_p_zz"_h, &VISITORCLASS::VisitSVEIntDivideVectors_Predicated}, \ + {"dup_z_i"_h, &VISITORCLASS::VisitSVEBroadcastIntImm_Unpredicated}, \ + {"fdup_z_i"_h, &VISITORCLASS::VisitSVEBroadcastFPImm_Unpredicated}, \ + {"dup_z_r"_h, &VISITORCLASS::VisitSVEBroadcastGeneralRegister}, \ + {"compact_z_p_z"_h, &VISITORCLASS::VisitSVECompressActiveElements}, \ + {"ctermeq_rr"_h, &VISITORCLASS::VisitSVEConditionallyTerminateScalars}, \ + {"ctermne_rr"_h, &VISITORCLASS::VisitSVEConditionallyTerminateScalars}, \ + {"clasta_r_p_z"_h, \ + &VISITORCLASS::VisitSVEConditionallyExtractElementToGeneralRegister}, \ + {"clastb_r_p_z"_h, \ + &VISITORCLASS::VisitSVEConditionallyExtractElementToGeneralRegister}, \ + {"asrd_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ + {"asr_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ + {"lsl_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ + {"lsr_z_p_zi"_h, &VISITORCLASS::VisitSVEBitwiseShiftByImm_Predicated}, \ + {"cpy_z_p_r"_h, \ + &VISITORCLASS::VisitSVECopyGeneralRegisterToVector_Predicated}, \ + {"cpy_z_o_i"_h, &VISITORCLASS::VisitSVECopyIntImm_Predicated}, \ + {"cpy_z_p_i"_h, &VISITORCLASS::VisitSVECopyIntImm_Predicated}, \ + {"cpy_z_p_v"_h, \ + &VISITORCLASS::VisitSVECopySIMDFPScalarRegisterToVector_Predicated}, \ + {"fcpy_z_p_i"_h, &VISITORCLASS::VisitSVECopyFPImm_Predicated}, \ + {"lasta_r_p_z"_h, \ + &VISITORCLASS::VisitSVEExtractElementToGeneralRegister}, \ + {"lastb_r_p_z"_h, \ + &VISITORCLASS::VisitSVEExtractElementToGeneralRegister}, \ + {"sdot_z_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddUnpredicated}, \ + {"udot_z_zzz"_h, &VISITORCLASS::VisitSVEIntMulAddUnpredicated}, \ + {"st1b_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ + {"st1d_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ + {"st1h_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ + {"st1w_z_p_bi"_h, &VISITORCLASS::VisitSVEContiguousStore_ScalarPlusImm}, \ + {"prfb_i_p_bi_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ + {"prfd_i_p_bi_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ + {"prfh_i_p_bi_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ + {"prfw_i_p_bi_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusImm}, \ + {"prfb_i_p_br_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ + {"prfd_i_p_br_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ + {"prfh_i_p_br_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ + {"prfw_i_p_br_s"_h, \ + &VISITORCLASS::VisitSVEContiguousPrefetch_ScalarPlusScalar}, \ + {"ldnf1b_z_p_bi_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1b_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1b_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1b_z_p_bi_u8"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1d_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1h_z_p_bi_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1h_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1h_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sb_z_p_bi_s16"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sb_z_p_bi_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sb_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sh_z_p_bi_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sh_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1sw_z_p_bi_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1w_z_p_bi_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"ldnf1w_z_p_bi_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousNonFaultLoad_ScalarPlusImm}, \ + {"prfb_i_p_bz_d_64_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ + {"prfd_i_p_bz_d_64_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ + {"prfh_i_p_bz_d_64_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ + {"prfw_i_p_bz_d_64_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets}, \ + {"prfb_i_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"prfd_i_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"prfh_i_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"prfw_i_p_bz_d_x32_scaled"_h, \ + &VISITORCLASS:: \ + VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets}, \ + {"prfb_i_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ + {"prfd_i_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ + {"prfh_i_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ + {"prfw_i_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherPrefetch_VectorPlusImm}, \ + {"prfb_i_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ + {"prfd_i_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ + {"prfh_i_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ + {"prfw_i_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherPrefetch_VectorPlusImm}, \ + {"ldr_z_bi"_h, &VISITORCLASS::VisitSVELoadVectorRegister}, \ + {"str_z_bi"_h, &VISITORCLASS::VisitSVEStoreVectorRegister}, \ + {"ldr_p_bi"_h, &VISITORCLASS::VisitSVELoadPredicateRegister}, \ + {"str_p_bi"_h, &VISITORCLASS::VisitSVEStorePredicateRegister}, \ + {"fcvt_z_p_z_d2h"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"fcvt_z_p_z_d2s"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"fcvt_z_p_z_h2d"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"fcvt_z_p_z_h2s"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"fcvt_z_p_z_s2d"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"fcvt_z_p_z_s2h"_h, &VISITORCLASS::VisitSVEFPConvertPrecision}, \ + {"ld1b_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ld1h_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ld1sb_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ld1sh_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ld1w_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ldff1b_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ldff1h_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ldff1sb_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ldff1sh_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"ldff1w_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitGatherLoad_VectorPlusImm}, \ + {"st1b_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ + {"st1h_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ + {"st1w_z_p_ai_s"_h, \ + &VISITORCLASS::VisitSVE32BitScatterStore_VectorPlusImm}, \ + {"st1b_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ + {"st1d_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ + {"st1h_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ + {"st1w_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitScatterStore_VectorPlusImm}, \ + {"ldff1b_z_p_br_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1b_z_p_br_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1b_z_p_br_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1b_z_p_br_u8"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1d_z_p_br_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1h_z_p_br_u16"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1h_z_p_br_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1h_z_p_br_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sb_z_p_br_s16"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sb_z_p_br_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sb_z_p_br_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sh_z_p_br_s32"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sh_z_p_br_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1sw_z_p_br_s64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1w_z_p_br_u32"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldff1w_z_p_br_u64"_h, \ + &VISITORCLASS::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar}, \ + {"ldnt1b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ + {"ldnt1d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ + {"ldnt1h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ + {"ldnt1w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm}, \ + {"stnt1b_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ + {"stnt1d_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ + {"stnt1h_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ + {"stnt1w_z_p_bi_contiguous"_h, \ + &VISITORCLASS::VisitSVEContiguousNonTemporalStore_ScalarPlusImm}, \ + {"ld1rb_z_p_bi_u16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rb_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rb_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rb_z_p_bi_u8"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rd_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rh_z_p_bi_u16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rh_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rh_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsb_z_p_bi_s16"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsb_z_p_bi_s32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsb_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsh_z_p_bi_s32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsh_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rsw_z_p_bi_s64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rw_z_p_bi_u32"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ + {"ld1rw_z_p_bi_u64"_h, &VISITORCLASS::VisitSVELoadAndBroadcastElement}, \ {"addp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"add_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"cmeq_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ @@ -2106,6 +2463,21 @@ {"cmhi_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"cmhs_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"cmtst_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqdmulh_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqrdmulh_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqrshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sqsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"srshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"sub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uqadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uqrshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uqshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"uqsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"urshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ + {"ushl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"fabd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"facge_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"facgt_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ @@ -2130,74 +2502,12 @@ {"frecps_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"frsqrts_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ {"fsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqdmulh_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqrdmulh_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqrshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sqsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"srshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uqadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uqrshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uqshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uqsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"urshl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"ushl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"fcadd_asimdsame2_c"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"fcmla_asimdsame2_c"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"sdot_asimdsame2_d"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"sqrdmlah_asimdsame2_only"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"sqrdmlsh_asimdsame2_only"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"udot_asimdsame2_d"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ - {"fabd_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"facge_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"facgt_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"faddp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fadd_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fcmeq_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fcmge_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fcmgt_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fdiv_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmaxnmp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmaxnm_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmaxp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmax_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fminnmp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fminnm_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fminp_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmin_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmla_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmls_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmulx_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fmul_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"frecps_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"frsqrts_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"fsub_asimdsamefp16_only"_h, &VISITORCLASS::VisitNEON3SameFP16}, \ - {"addv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"saddlv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"smaxv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"sminv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"uaddlv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"umaxv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"uminv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"mla_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"mls_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"mul_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"sqdmulh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"sqrdmlah_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"sqrdmlsh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"sqrdmulh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ - {"dup_asimdins_dr_r"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"dup_asimdins_dv_v"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"ins_asimdins_ir_r"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"ins_asimdins_iv_v"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"smov_asimdins_w_w"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"smov_asimdins_x_x"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"umov_asimdins_w_w"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"umov_asimdins_x_x"_h, &VISITORCLASS::VisitNEONCopy}, \ - {"ext_asimdext_only"_h, &VISITORCLASS::VisitNEONExtract}, \ + {"trn1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ + {"trn2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ + {"uzp1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ + {"uzp2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ + {"zip1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ + {"zip2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ {"ld1_asisdlse_r1_1v"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ {"ld1_asisdlse_r2_2v"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ {"ld1_asisdlse_r3_3v"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ @@ -2212,441 +2522,326 @@ {"st2_asisdlse_r2"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ {"st3_asisdlse_r3"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ {"st4_asisdlse_r4"_h, &VISITORCLASS::VisitNEONLoadStoreMultiStruct}, \ - {"ld1_asisdlsep_i1_i1"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_i2_i2"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_i3_i3"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_i4_i4"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_r1_r1"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_r2_r2"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_r3_r3"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1_asisdlsep_r4_r4"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld2_asisdlsep_i2_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld2_asisdlsep_r2_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld3_asisdlsep_i3_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld3_asisdlsep_r3_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld4_asisdlsep_i4_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld4_asisdlsep_r4_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_i1_i1"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_i2_i2"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_i3_i3"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_i4_i4"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_r1_r1"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_r2_r2"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_r3_r3"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st1_asisdlsep_r4_r4"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st2_asisdlsep_i2_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st2_asisdlsep_r2_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st3_asisdlsep_i3_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st3_asisdlsep_r3_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st4_asisdlsep_i4_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"st4_asisdlsep_r4_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreMultiStructPostIndex}, \ - {"ld1r_asisdlso_r1"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld1_asisdlso_b1_1b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld1_asisdlso_d1_1d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld1_asisdlso_h1_1h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld1_asisdlso_s1_1s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld2r_asisdlso_r2"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld2_asisdlso_b2_2b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld2_asisdlso_d2_2d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld2_asisdlso_h2_2h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld2_asisdlso_s2_2s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld3r_asisdlso_r3"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld3_asisdlso_b3_3b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld3_asisdlso_d3_3d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld3_asisdlso_h3_3h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld3_asisdlso_s3_3s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld4r_asisdlso_r4"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld4_asisdlso_b4_4b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld4_asisdlso_d4_4d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld4_asisdlso_h4_4h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld4_asisdlso_s4_4s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st1_asisdlso_b1_1b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st1_asisdlso_d1_1d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st1_asisdlso_h1_1h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st1_asisdlso_s1_1s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st2_asisdlso_b2_2b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st2_asisdlso_d2_2d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st2_asisdlso_h2_2h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st2_asisdlso_s2_2s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st3_asisdlso_b3_3b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st3_asisdlso_d3_3d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st3_asisdlso_h3_3h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st3_asisdlso_s3_3s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st4_asisdlso_b4_4b"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st4_asisdlso_d4_4d"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st4_asisdlso_h4_4h"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"st4_asisdlso_s4_4s"_h, &VISITORCLASS::VisitNEONLoadStoreSingleStruct}, \ - {"ld1r_asisdlsop_r1_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1r_asisdlsop_rx1_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_b1_i1b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_bx1_r1b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_d1_i1d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_dx1_r1d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_h1_i1h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_hx1_r1h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_s1_i1s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld1_asisdlsop_sx1_r1s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2r_asisdlsop_r2_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2r_asisdlsop_rx2_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_b2_i2b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_bx2_r2b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_d2_i2d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_dx2_r2d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_h2_i2h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_hx2_r2h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_s2_i2s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld2_asisdlsop_sx2_r2s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3r_asisdlsop_r3_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3r_asisdlsop_rx3_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_b3_i3b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_bx3_r3b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_d3_i3d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_dx3_r3d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_h3_i3h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_hx3_r3h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_s3_i3s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld3_asisdlsop_sx3_r3s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4r_asisdlsop_r4_i"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4r_asisdlsop_rx4_r"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_b4_i4b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_bx4_r4b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_d4_i4d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_dx4_r4d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_h4_i4h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_hx4_r4h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_s4_i4s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"ld4_asisdlsop_sx4_r4s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_b1_i1b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_bx1_r1b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_d1_i1d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_dx1_r1d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_h1_i1h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_hx1_r1h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_s1_i1s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st1_asisdlsop_sx1_r1s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_b2_i2b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_bx2_r2b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_d2_i2d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_dx2_r2d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_h2_i2h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_hx2_r2h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_s2_i2s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st2_asisdlsop_sx2_r2s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_b3_i3b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_bx3_r3b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_d3_i3d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_dx3_r3d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_h3_i3h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_hx3_r3h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_s3_i3s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st3_asisdlsop_sx3_r3s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_b4_i4b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_bx4_r4b"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_d4_i4d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_dx4_r4d"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_h4_i4h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_hx4_r4h"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_s4_i4s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"st4_asisdlsop_sx4_r4s"_h, \ - &VISITORCLASS::VisitNEONLoadStoreSingleStructPostIndex}, \ - {"bic_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"bic_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"fmov_asimdimm_d2_d"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"fmov_asimdimm_h_h"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"fmov_asimdimm_s_s"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_d2_d"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_d_ds"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_m_sm"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"movi_asimdimm_n_b"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"mvni_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"mvni_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"mvni_asimdimm_m_sm"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"orr_asimdimm_l_hl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"orr_asimdimm_l_sl"_h, &VISITORCLASS::VisitNEONModifiedImmediate}, \ - {"trn1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"trn2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"uzp1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"uzp2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"zip1_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"zip2_asimdperm_only"_h, &VISITORCLASS::VisitNEONPerm}, \ - {"sqabs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"sqneg_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"sqxtn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"sqxtun_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"suqadd_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"uqxtn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"usqadd_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmeq_asisdmiscfp16_fz"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcmge_asisdmiscfp16_fz"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcmgt_asisdmiscfp16_fz"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcmle_asisdmiscfp16_fz"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcmlt_asisdmiscfp16_fz"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtas_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtau_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtms_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtmu_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtns_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtnu_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtps_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtpu_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtzs_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"fcvtzu_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"frecpe_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"frecpx_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"frsqrte_asisdmiscfp16_r"_h, \ - &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"scvtf_asisdmiscfp16_r"_h, &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"ucvtf_asisdmiscfp16_r"_h, &VISITORCLASS::VisitNEONScalar2RegMiscFP16}, \ - {"sqdmlal_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ - {"sqdmlsl_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ - {"sqdmull_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ - {"sqadd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqdmulh_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqrdmulh_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqrshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqsub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"srshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"uqadd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"uqrshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"uqshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"uqsub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"urshl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"ushl_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"fabd_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"facge_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"facgt_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"fcmeq_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"fcmge_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"fcmgt_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"fmulx_asisdsamefp16_only"_h, &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"frecps_asisdsamefp16_only"_h, \ - &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"frsqrts_asisdsamefp16_only"_h, \ - &VISITORCLASS::VisitNEONScalar3SameFP16}, \ - {"sqdmulh_asisdelem_r"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"sqrdmlah_asisdelem_r"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"sqrdmlsh_asisdelem_r"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"sqrdmulh_asisdelem_r"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"dup_asisdone_only"_h, &VISITORCLASS::VisitNEONScalarCopy}, \ - {"addp_asisdpair_only"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"faddp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"faddp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fmaxnmp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fmaxnmp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fmaxp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fmaxp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fminnmp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fminnmp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fminp_asisdpair_only_h"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fminp_asisdpair_only_sd"_h, &VISITORCLASS::VisitNEONScalarPairwise}, \ - {"fcvtzs_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"fcvtzu_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"scvtf_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqshlu_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqshl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"ucvtf_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"uqshl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"fcadd_asimdsame2_c"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"fcmla_asimdsame2_c"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"sdot_asimdsame2_d"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"sqrdmlah_asimdsame2_only"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"sqrdmlsh_asimdsame2_only"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"udot_asimdsame2_d"_h, &VISITORCLASS::VisitNEON3SameExtra}, \ + {"abs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cls_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"clz_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cmeq_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cmge_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cmgt_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cmle_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"cmlt_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"neg_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"not_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"rev32_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"rev64_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"sadalp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"saddlp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"shll_asimdmisc_s"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"sqabs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"sqneg_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"sqxtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"sqxtun_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"suqadd_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"uadalp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"uaddlp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"uqxtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"usqadd_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"xtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ + {"mla_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"mls_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"mul_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"sqdmulh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"sqrdmlah_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"sqrdmlsh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"sqrdmulh_asimdelem_r"_h, &VISITORCLASS::VisitNEONByIndexedElement}, \ + {"ld1b_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1d_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1h_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1sb_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1sh_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1sw_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ld1w_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1b_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1d_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1h_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1sb_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1sh_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1sw_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ + {"ldff1w_z_p_ai_d"_h, \ + &VISITORCLASS::VisitSVE64BitGatherLoad_VectorPlusImm}, \ {"sqshlu_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ {"sqshl_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ {"uqshl_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ {"shl_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ {"sli_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"tbl_asimdtbl_l1_1"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbl_asimdtbl_l2_2"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbl_asimdtbl_l3_3"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbl_asimdtbl_l4_4"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbx_asimdtbl_l1_1"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbx_asimdtbl_l2_2"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbx_asimdtbl_l3_3"_h, &VISITORCLASS::VisitNEONTable}, \ - {"tbx_asimdtbl_l4_4"_h, &VISITORCLASS::VisitNEONTable}, \ - {"adrp_only_pcreladdr"_h, &VISITORCLASS::VisitPCRelAddressing}, \ - {"adr_only_pcreladdr"_h, &VISITORCLASS::VisitPCRelAddressing}, \ - {"rmif_only_rmif"_h, &VISITORCLASS::VisitRotateRightIntoFlags}, \ + {"dup_asimdins_dr_r"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"dup_asimdins_dv_v"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"ins_asimdins_ir_r"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"ins_asimdins_iv_v"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"smov_asimdins_w_w"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"smov_asimdins_x_x"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"umov_asimdins_w_w"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"umov_asimdins_x_x"_h, &VISITORCLASS::VisitNEONCopy}, \ + {"sqabs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"sqneg_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"suqadd_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"usqadd_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"sqxtn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"sqxtun_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"uqxtn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ + {"sqdmlal_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ + {"sqdmlsl_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ + {"sqdmull_asisddiff_only"_h, &VISITORCLASS::VisitNEONScalar3Diff}, \ + {"dup_asisdone_only"_h, &VISITORCLASS::VisitNEONScalarCopy}, \ + {"saddlv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"uaddlv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"addv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"smaxv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"sminv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"umaxv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"uminv_asimdall_only"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ + {"sqshlu_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sqshl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"uqshl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"fcvtzs_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"fcvtzu_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"scvtf_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"ucvtf_asisdshf_c"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ + {"sabal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"sabdl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"saddl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"smlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"smlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"smull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"ssubl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"uabal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"uabdl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"uaddl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"umlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"umlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"umull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"usubl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"saddw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"ssubw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"uaddw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"usubw_asimddiff_w"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"addhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"raddhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"rsubhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"subhn_asimddiff_n"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"sqdmlal_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"sqdmlsl_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"sqdmull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ + {"movk_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"movk_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"movz_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"movz_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"movn_32_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"movn_64_movewide"_h, &VISITORCLASS::VisitMoveWideImmediate}, \ + {"decb_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"decd_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"dech_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"decw_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"incb_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"incd_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"inch_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"incw_r_rs"_h, &VISITORCLASS::VisitSVEIncDecRegisterByElementCount}, \ + {"cntb_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ + {"cntd_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ + {"cnth_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ + {"cntw_r_s"_h, &VISITORCLASS::VisitSVEElementCount}, \ + {"decd_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"dech_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"decw_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"incd_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"inch_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"incw_z_zs"_h, &VISITORCLASS::VisitSVEIncDecVectorByElementCount}, \ + {"sqdecd_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqdech_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqdecw_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqincd_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqinch_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqincw_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqdecd_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqdech_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqdecw_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqincd_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqinch_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"uqincw_z_zs"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecVectorByElementCount}, \ + {"sqdecb_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdecb_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdecd_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdecd_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdech_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdech_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdecw_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqdecw_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincb_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincb_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincd_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincd_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqinch_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqinch_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincw_r_rs_sx"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"sqincw_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecb_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecb_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecd_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecd_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdech_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdech_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecw_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqdecw_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincb_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincb_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincd_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincd_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqinch_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqinch_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincw_r_rs_uw"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"uqincw_r_rs_x"_h, \ + &VISITORCLASS::VisitSVESaturatingIncDecRegisterByElementCount}, \ + {"cas_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casa_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casl_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casal_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casab_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caslb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casalb_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"cash_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casah_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caslh_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casalh_c32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"cas_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casa_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casl_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casal_c64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxrb_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxrh_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxr_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxrb_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxrh_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxr_sr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxr_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxr_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldar_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldlar_lr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlr_sl64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stllr_sl64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxr_sr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxr_sr64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxp_lp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxp_lp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxp_lp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxp_lp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxp_sp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxp_sp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stxp_sp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlxp_sp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casp_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspa_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspl_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspal_cp32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"casp_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspa_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspl_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"caspal_cp64_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldarb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldarh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldar_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxrb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxrh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldaxr_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldlarb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldlarh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldlar_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxrb_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxrh_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"ldxr_lr32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stllrb_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stllrh_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stllr_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlrb_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlrh_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"stlr_sl32_ldstexcl"_h, &VISITORCLASS::VisitLoadStoreExclusive}, \ + {"dup_z_zi"_h, &VISITORCLASS::VisitSVEBroadcastIndexElement}, \ {"bti_hb_hints"_h, &VISITORCLASS::VisitSystem}, \ {"clrex_bn_barriers"_h, &VISITORCLASS::VisitSystem}, \ {"dmb_bo_barriers"_h, &VISITORCLASS::VisitSystem}, \ {"dsb_bo_barriers"_h, &VISITORCLASS::VisitSystem}, \ {"hint_hm_hints"_h, &VISITORCLASS::VisitSystem}, \ {"chkfeat_hf_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"mrs_rs_systemmove"_h, &VISITORCLASS::VisitSystem}, \ - {"msr_sr_systemmove"_h, &VISITORCLASS::VisitSystem}, \ - {"psb_hc_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"sb_only_barriers"_h, &VISITORCLASS::VisitSystem}, \ {"sysl_rc_systeminstrs"_h, &VISITORCLASS::VisitSystem}, \ {"sys_cr_systeminstrs"_h, &VISITORCLASS::VisitSystem}, \ {"tcommit_only_barriers"_h, &VISITORCLASS::VisitSystem}, \ {"tsb_hc_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"tbnz_only_testbranch"_h, &VISITORCLASS::VisitTestBranch}, \ - {"tbz_only_testbranch"_h, &VISITORCLASS::VisitTestBranch}, \ - {"bl_only_branch_imm"_h, &VISITORCLASS::VisitUnconditionalBranch}, \ - {"b_only_branch_imm"_h, &VISITORCLASS::VisitUnconditionalBranch}, \ - {"blraaz_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"blraa_64p_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"blrabz_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"blrab_64p_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"blr_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"braaz_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"braa_64p_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"brabz_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"brab_64p_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"br_64_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"drps_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"eretaa_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"eretab_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"eret_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"retaa_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"retab_64e_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"ret_64r_branch_reg"_h, \ - &VISITORCLASS::VisitUnconditionalBranchToRegister}, \ - {"bfcvtn_asimdmisc_4s"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfdot_asimdelem_e"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfdot_asimdsame2_d"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlal_asimdelem_f"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlal_asimdsame2_f"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmmla_asimdsame2_e"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"dsb_bon_barriers"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"ld64b_64l_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"ldgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ + {"psb_hc_hints"_h, &VISITORCLASS::VisitSystem}, \ + {"sb_only_barriers"_h, &VISITORCLASS::VisitSystem}, \ + {"mrs_rs_systemmove"_h, &VISITORCLASS::VisitSystem}, \ + {"msr_sr_systemmove"_h, &VISITORCLASS::VisitSystem}, \ {"ldtrb_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"ldtrh_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"ldtrsb_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ @@ -2656,287 +2851,16 @@ {"ldtrsw_64_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"ldtr_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"ldtr_64_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"sm3partw1_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3partw2_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3ss1_vvv4_crypto4"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3tt1a_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3tt1b_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3tt2a_vvv4_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm3tt2b_vvv_crypto3_imm2"_h, &VISITORCLASS::VisitCryptoSM3}, \ - {"sm4ekey_vvv4_cryptosha512_3"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"sm4e_vv4_cryptosha512_2"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"st64b_64l_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"st64bv_64_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"st64bv0_64_memop"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"stgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ {"sttrb_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"sttrh_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"sttr_32_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ {"sttr_64_ldst_unpriv"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"stzgm_64bulk_ldsttags"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"tcancel_ex_exception"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"tstart_br_systemresult"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"ttest_br_systemresult"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"wfet_only_systeminstrswithreg"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"wfit_only_systeminstrswithreg"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfcvt_z_p_z_s2bf"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfcvtnt_z_p_z_s2bf"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfdot_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfdot_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlalb_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlalb_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlalt_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmlalt_z_zzzi"_h, &VISITORCLASS::VisitUnimplemented}, \ - {"bfmmla_z_zzz"_h, &VISITORCLASS::VisitUnimplemented}, { \ - "unallocated"_h, &VISITORCLASS::VisitUnallocated \ - } - -#define SIM_AUD_VISITOR_MAP(VISITORCLASS) \ - {"autia1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"autiasp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"autiaz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"autib1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"autibsp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"autibz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"axflag_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ - {"cfinv_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ - {"csdb_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"dgh_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"esb_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"isb_bi_barriers"_h, &VISITORCLASS::VisitSystem}, \ - {"nop_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"pacia1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"paciasp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"paciaz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"pacib1716_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"pacibsp_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"pacibz_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"sev_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"sevl_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"ssbb_only_barriers"_h, &VISITORCLASS::VisitSystem}, \ - {"wfe_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"wfi_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"xaflag_m_pstate"_h, &VISITORCLASS::VisitSystem}, \ - {"xpaclri_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"yield_hi_hints"_h, &VISITORCLASS::VisitSystem}, \ - {"abs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cls_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"clz_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cmeq_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cmge_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cmgt_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cmle_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cmlt_asimdmisc_z"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"cnt_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fabs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcmeq_asimdmisc_fz"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcmge_asimdmisc_fz"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcmgt_asimdmisc_fz"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcmle_asimdmisc_fz"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcmlt_asimdmisc_fz"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtas_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtau_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtl_asimdmisc_l"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtms_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtmu_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtns_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtnu_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtps_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtpu_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtxn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtzs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fcvtzu_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fneg_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frecpe_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frint32x_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frint32z_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frint64x_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frint64z_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frinta_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frinti_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frintm_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frintn_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frintp_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frintx_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frintz_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"frsqrte_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"fsqrt_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"neg_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"not_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"rbit_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"rev16_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"rev32_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"rev64_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"sadalp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"saddlp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"scvtf_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"shll_asimdmisc_s"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"sqabs_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"sqneg_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"sqxtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"sqxtun_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"suqadd_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"uadalp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"uaddlp_asimdmisc_p"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"ucvtf_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"uqxtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"urecpe_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"ursqrte_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"usqadd_asimdmisc_r"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"xtn_asimdmisc_n"_h, &VISITORCLASS::VisitNEON2RegMisc}, \ - {"mla_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"mls_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"mul_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"saba_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sabd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"shadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"shsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"smaxp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"smax_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"sminp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"smin_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"srhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uaba_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uabd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uhsub_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"umaxp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"umax_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"uminp_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"umin_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"urhadd_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"and_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"bic_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"bif_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"bit_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"bsl_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"eor_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"orr_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"orn_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"pmul_asimdsame_only"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"fmlal2_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"fmlal_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"fmlsl2_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"fmlsl_asimdsame_f"_h, &VISITORCLASS::VisitNEON3Same}, \ - {"pmull_asimddiff_l"_h, &VISITORCLASS::VisitNEON3Different}, \ - {"ushll_asimdshf_l"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sshll_asimdshf_l"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"shrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"rshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sqshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sqrshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sqshrun_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sqrshrun_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"uqshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"uqrshrn_asimdshf_n"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sri_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"srshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"srsra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"ssra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"urshr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"ursra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"ushr_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"usra_asimdshf_r"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"scvtf_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"ucvtf_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"fcvtzs_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"fcvtzu_asimdshf_c"_h, &VISITORCLASS::VisitNEONShiftImmediate}, \ - {"sqdmlal_asisdelem_l"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"sqdmlsl_asisdelem_l"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"sqdmull_asisdelem_l"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmla_asisdelem_rh_h"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmla_asisdelem_r_sd"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmls_asisdelem_rh_h"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmls_asisdelem_r_sd"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmulx_asisdelem_rh_h"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmulx_asisdelem_r_sd"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmul_asisdelem_rh_h"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fmul_asisdelem_r_sd"_h, \ - &VISITORCLASS::VisitNEONScalarByIndexedElement}, \ - {"fabd_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"facge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"facgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"fcmeq_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"fcmge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"fcmgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"fmulx_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"frecps_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"frsqrts_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmeq_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmge_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmgt_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmhi_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmhs_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"cmtst_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"add_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sub_asisdsame_only"_h, &VISITORCLASS::VisitNEONScalar3Same}, \ - {"sqrdmlah_asisdsame2_only"_h, \ - &VISITORCLASS::VisitNEONScalar3SameExtra}, \ - {"sqrdmlsh_asisdsame2_only"_h, \ - &VISITORCLASS::VisitNEONScalar3SameExtra}, \ - {"fmaxnmv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fmaxv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fminnmv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fminv_asimdall_only_h"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fmaxnmv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fminnmv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fmaxv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"fminv_asimdall_only_sd"_h, &VISITORCLASS::VisitNEONAcrossLanes}, \ - {"shl_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sli_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sri_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"srshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"srsra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"ssra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"urshr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"ursra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"ushr_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"usra_asisdshf_r"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqrshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqrshrun_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"sqshrun_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"uqrshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"uqshrn_asisdshf_n"_h, &VISITORCLASS::VisitNEONScalarShiftImmediate}, \ - {"cmeq_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"cmge_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"cmgt_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"cmle_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"cmlt_asisdmisc_z"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"abs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"neg_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmeq_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmge_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmgt_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmle_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcmlt_asisdmisc_fz"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtas_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtau_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtms_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtmu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtns_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtnu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtps_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtpu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtxn_asisdmisc_n"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtzs_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"fcvtzu_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"frecpe_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"frecpx_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"frsqrte_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, \ - {"scvtf_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc}, { \ - "ucvtf_asisdmisc_r"_h, &VISITORCLASS::VisitNEONScalar2RegMisc \ + {"adcs_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"adcs_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"adc_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"adc_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"sbcs_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"sbcs_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, \ + {"sbc_32_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry}, { \ + "sbc_64_addsub_carry"_h, &VISITORCLASS::VisitAddSubWithCarry \ } diff --git a/3rdparty/vixl/include/vixl/aarch64/disasm-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/disasm-aarch64.h index b139c4c24c..d044974de4 100644 --- a/3rdparty/vixl/include/vixl/aarch64/disasm-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/disasm-aarch64.h @@ -117,11 +117,17 @@ class Disassembler : public DecoderVisitor { VISITOR_LIST(DECLARE) #undef DECLARE + std::string GetMnemonicAlias(const Instruction* instr); + using FormToVisitorFnMap = std::unordered_map< uint32_t, std::function>; static const FormToVisitorFnMap* GetFormToVisitorFnMap(); + using FormToStringMap = std::unordered_map; + static void PopulateFormToStringMap(FormToStringMap* fts); + + FormToStringMap form_to_string_; std::string mnemonic_; uint32_t form_hash_; @@ -132,119 +138,6 @@ class Disassembler : public DecoderVisitor { } } - void Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction* instr); - void Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction* instr); - void Disassemble_ZdB_ZnB_ZmB(const Instruction* instr); - void Disassemble_ZdD_PgM_ZnS(const Instruction* instr); - void Disassemble_ZdD_ZnD_ZmD(const Instruction* instr); - void Disassemble_ZdD_ZnD_ZmD_imm(const Instruction* instr); - void Disassemble_ZdD_ZnS_ZmS_imm(const Instruction* instr); - void Disassemble_ZdH_PgM_ZnS(const Instruction* instr); - void Disassemble_ZdH_ZnH_ZmH_imm(const Instruction* instr); - void Disassemble_ZdS_PgM_ZnD(const Instruction* instr); - void Disassemble_ZdS_PgM_ZnH(const Instruction* instr); - void Disassemble_ZdS_PgM_ZnS(const Instruction* instr); - void Disassemble_ZdS_ZnH_ZmH_imm(const Instruction* instr); - void Disassemble_ZdS_ZnS_ZmS(const Instruction* instr); - void Disassemble_ZdS_ZnS_ZmS_imm(const Instruction* instr); - void Disassemble_ZdT_PgM_ZnT(const Instruction* instr); - void Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction* instr); - void Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr); - void Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction* instr); - void Disassemble_ZdT_ZnT_ZmT(const Instruction* instr); - void Disassemble_ZdT_ZnT_ZmTb(const Instruction* instr); - void Disassemble_ZdT_ZnTb(const Instruction* instr); - void Disassemble_ZdT_ZnTb_ZmTb(const Instruction* instr); - void Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction* instr); - void Disassemble_ZdaD_ZnH_ZmH_imm_const(const Instruction* instr); - void Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction* instr); - void Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction* instr); - void Disassemble_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr); - void Disassemble_ZdaS_ZnB_ZmB_imm_const(const Instruction* instr); - void Disassemble_ZdaS_ZnH_ZmH(const Instruction* instr); - void Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction* instr); - void Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction* instr); - void Disassemble_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr); - void Disassemble_ZdaT_PgM_ZnTb(const Instruction* instr); - void Disassemble_ZdaT_ZnT_ZmT(const Instruction* instr); - void Disassemble_ZdaT_ZnT_ZmT_const(const Instruction* instr); - void Disassemble_ZdaT_ZnT_const(const Instruction* instr); - void Disassemble_ZdaT_ZnTb_ZmTb(const Instruction* instr); - void Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction* instr); - void Disassemble_ZdnB_ZdnB(const Instruction* instr); - void Disassemble_ZdnB_ZdnB_ZmB(const Instruction* instr); - void Disassemble_ZdnS_ZdnS_ZmS(const Instruction* instr); - void Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr); - void Disassemble_ZdnT_PgM_ZdnT_const(const Instruction* instr); - void Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction* instr); - void Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction* instr); - void Disassemble_ZtD_Pg_ZnD_Xm(const Instruction* instr); - void Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction* instr); - void Disassemble_ZtS_Pg_ZnS_Xm(const Instruction* instr); - void Disassemble_ZdaS_ZnB_ZmB(const Instruction* instr); - void Disassemble_Vd4S_Vn16B_Vm16B(const Instruction* instr); - - void DisassembleCpy(const Instruction* instr); - void DisassembleSet(const Instruction* instr); - void DisassembleMinMaxImm(const Instruction* instr); - - void DisassembleSVEShiftLeftImm(const Instruction* instr); - void DisassembleSVEShiftRightImm(const Instruction* instr); - void DisassembleSVEAddSubCarry(const Instruction* instr); - void DisassembleSVEAddSubHigh(const Instruction* instr); - void DisassembleSVEComplexIntAddition(const Instruction* instr); - void DisassembleSVEBitwiseTernary(const Instruction* instr); - void DisassembleSVEFlogb(const Instruction* instr); - void DisassembleSVEFPPair(const Instruction* instr); - - void DisassembleNoArgs(const Instruction* instr); - - void DisassembleNEONMulByElementLong(const Instruction* instr); - void DisassembleNEONDotProdByElement(const Instruction* instr); - void DisassembleNEONFPMulByElement(const Instruction* instr); - void DisassembleNEONHalfFPMulByElement(const Instruction* instr); - void DisassembleNEONFPMulByElementLong(const Instruction* instr); - void DisassembleNEONComplexMulByElement(const Instruction* instr); - void DisassembleNEON2RegLogical(const Instruction* instr); - void DisassembleNEON2RegExtract(const Instruction* instr); - void DisassembleNEON2RegAddlp(const Instruction* instr); - void DisassembleNEON2RegCompare(const Instruction* instr); - void DisassembleNEON2RegFPCompare(const Instruction* instr); - void DisassembleNEON2RegFPConvert(const Instruction* instr); - void DisassembleNEON2RegFP(const Instruction* instr); - void DisassembleNEON3SameLogical(const Instruction* instr); - void DisassembleNEON3SameFHM(const Instruction* instr); - void DisassembleNEON3SameNoD(const Instruction* instr); - void DisassembleNEONShiftLeftLongImm(const Instruction* instr); - void DisassembleNEONShiftRightImm(const Instruction* instr); - void DisassembleNEONShiftRightNarrowImm(const Instruction* instr); - void DisassembleNEONScalarSatMulLongIndex(const Instruction* instr); - void DisassembleNEONFPScalarMulIndex(const Instruction* instr); - void DisassembleNEONFPScalar3Same(const Instruction* instr); - void DisassembleNEONScalar3SameOnlyD(const Instruction* instr); - void DisassembleNEONFPAcrossLanes(const Instruction* instr); - void DisassembleNEONFP16AcrossLanes(const Instruction* instr); - void DisassembleNEONScalarShiftImmOnlyD(const Instruction* instr); - void DisassembleNEONScalarShiftRightNarrowImm(const Instruction* instr); - void DisassembleNEONScalar2RegMiscOnlyD(const Instruction* instr); - void DisassembleNEONFPScalar2RegMisc(const Instruction* instr); - void DisassembleNEONPolynomialMul(const Instruction* instr); - void DisassembleNEON4Same(const Instruction* instr); - void DisassembleNEONXar(const Instruction* instr); - void DisassembleNEONRax1(const Instruction* instr); - void DisassembleSHA512(const Instruction* instr); - - void DisassembleMTELoadTag(const Instruction* instr); - void DisassembleMTEStoreTag(const Instruction* instr); - void DisassembleMTEStoreTagPair(const Instruction* instr); - - void Disassemble_XdSP_XnSP_Xm(const Instruction* instr); - void Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction* instr); - void Disassemble_Xd_XnSP_Xm(const Instruction* instr); - void Disassemble_Xd_XnSP_XmSP(const Instruction* instr); - - void VisitCryptoSM3(const Instruction* instr); - void Format(const Instruction* instr, const char* mnemonic, const char* format0, @@ -253,42 +146,39 @@ class Disassembler : public DecoderVisitor { const char* format0, const char* format1 = NULL); - void Substitute(const Instruction* instr, const char* string); + int Substitute(const Instruction* instr, const char* string); int SubstituteField(const Instruction* instr, const char* format); int SubstituteRegisterField(const Instruction* instr, const char* format); int SubstitutePredicateRegisterField(const Instruction* instr, const char* format); int SubstituteImmediateField(const Instruction* instr, const char* format); int SubstituteLiteralField(const Instruction* instr, const char* format); - int SubstituteBitfieldImmediateField(const Instruction* instr, - const char* format); - int SubstituteShiftField(const Instruction* instr, const char* format); - int SubstituteExtendField(const Instruction* instr, const char* format); - int SubstituteConditionField(const Instruction* instr, const char* format); int SubstitutePCRelAddressField(const Instruction* instr, const char* format); int SubstituteBranchTargetField(const Instruction* instr, const char* format); int SubstituteLSRegOffsetField(const Instruction* instr, const char* format); - int SubstitutePrefetchField(const Instruction* instr, const char* format); - int SubstituteBarrierField(const Instruction* instr, const char* format); - int SubstituteSysOpField(const Instruction* instr, const char* format); - int SubstituteCrField(const Instruction* instr, const char* format); int SubstituteIntField(const Instruction* instr, const char* format); - int SubstituteSVESize(const Instruction* instr, const char* format); + int SubstituteFPField(const Instruction* instr, const char* format); int SubstituteTernary(const Instruction* instr, const char* format); + int SubstituteConditionalBlock(const Instruction* instr, const char* format); + int SubstituteGenericArray(const Instruction* instr, const char* format); + int SubstituteGenericHash(const Instruction* instr, const char* format); + int SubstituteExpression(const Instruction* instr, const char* format); + int SubstituteEnd(const Instruction* instr, const char* format); std::pair GetRegNumForField(const Instruction* instr, char reg_prefix, const char* field); - bool RdIsZROrSP(const Instruction* instr) const { + public: + static bool RdIsZROrSP(const Instruction* instr) { return (instr->GetRd() == kZeroRegCode); } - bool RnIsZROrSP(const Instruction* instr) const { + static bool RnIsZROrSP(const Instruction* instr) { return (instr->GetRn() == kZeroRegCode); } - bool RmIsZROrSP(const Instruction* instr) const { + static bool RmIsZROrSP(const Instruction* instr) { return (instr->GetRm() == kZeroRegCode); } @@ -298,6 +188,7 @@ class Disassembler : public DecoderVisitor { bool IsMovzMovnImm(unsigned reg_size, uint64_t value); + private: int64_t code_address_offset() const { return code_address_offset_; } protected: diff --git a/3rdparty/vixl/include/vixl/aarch64/instructions-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/instructions-aarch64.h index ce08ea3bd8..00aeb3cf84 100644 --- a/3rdparty/vixl/include/vixl/aarch64/instructions-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/instructions-aarch64.h @@ -373,6 +373,7 @@ class Instruction { std::pair GetSVEPermuteIndexAndLaneSizeLog2() const; + std::pair GetNEONMulRmAndIndex() const; std::pair GetSVEMulZmAndIndex() const; std::pair GetSVEMulLongZmAndIndex() const; @@ -855,11 +856,13 @@ class NEONFormatDecoder { // Set the format mapping for all or individual substitutions. void SetFormatMaps(const NEONFormatMap* format0, const NEONFormatMap* format1 = NULL, - const NEONFormatMap* format2 = NULL) { + const NEONFormatMap* format2 = NULL, + const NEONFormatMap* format3 = NULL) { VIXL_ASSERT(format0 != NULL); formats_[0] = format0; formats_[1] = (format1 == NULL) ? formats_[0] : format1; formats_[2] = (format2 == NULL) ? formats_[1] : format2; + formats_[3] = (format3 == NULL) ? formats_[2] : format3; } void SetFormatMap(unsigned index, const NEONFormatMap* format) { VIXL_ASSERT(index <= ArrayLength(formats_)); @@ -878,12 +881,15 @@ class NEONFormatDecoder { const char* Substitute(const char* string, SubstitutionMode mode0 = kFormat, SubstitutionMode mode1 = kFormat, - SubstitutionMode mode2 = kFormat) { + SubstitutionMode mode2 = kFormat, + SubstitutionMode mode3 = kFormat) { const char* subst0 = GetSubstitute(0, mode0); const char* subst1 = GetSubstitute(1, mode1); const char* subst2 = GetSubstitute(2, mode2); + const char* subst3 = GetSubstitute(3, mode3); - if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL)) { + if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL) || + (subst3 == NULL)) { return NULL; } @@ -892,7 +898,8 @@ class NEONFormatDecoder { string, subst0, subst1, - subst2); + subst2, + subst3); return form_buffer_; } @@ -1130,7 +1137,7 @@ class NEONFormatDecoder { } Instr instrbits_; - const NEONFormatMap* formats_[3]; + const NEONFormatMap* formats_[4]; char form_buffer_[64]; char mne_buffer_[16]; }; diff --git a/3rdparty/vixl/include/vixl/aarch64/macro-assembler-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/macro-assembler-aarch64.h index b74be350ff..02f06e07dd 100644 --- a/3rdparty/vixl/include/vixl/aarch64/macro-assembler-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/macro-assembler-aarch64.h @@ -1099,11 +1099,24 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { } } + void B(Label* label); void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1); - void B(Label* label); - void B(Label* label, Condition cond); + void B(Label* label, Condition cond) { + Bcommon(label, cond, /* use_bc = */ false); + } + void Bc(Label* label, Condition cond) { + Bcommon(label, cond, /* use_bc = */ true); + } + // Aliases that match the instruction set ordering. void B(Condition cond, Label* label) { B(label, cond); } + void Bc(Condition cond, Label* label) { Bc(label, cond); } + + private: + // Common method for B and Bc. + void Bcommon(Label* label, Condition cond, bool use_bc); + + public: void Bfm(const Register& rd, const Register& rn, unsigned immr, @@ -1190,6 +1203,31 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { SingleEmissionCheckScope guard(this); retab(); } + void Bfcvt(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + bfcvt(vd, vn); + } + void Bfcvtn(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + bfcvtn(vd, vn); + } + void Bfcvtn2(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + bfcvtn2(vd, vn); + } + void Bfcvt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + bfcvt(zd, pg, zn); + } + void Bfcvtnt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + bfcvtnt(zd, pg, zn); + } void Braa(const Register& xn, const Register& xm) { VIXL_ASSERT(allow_macro_instructions_); SingleEmissionCheckScope guard(this); @@ -2814,6 +2852,7 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { V(shsub, Shsub) \ V(sm3partw1, Sm3partw1) \ V(sm3partw2, Sm3partw2) \ + V(sm4ekey, Sm4ekey) \ V(smax, Smax) \ V(smaxp, Smaxp) \ V(smin, Smin) \ @@ -2964,6 +3003,7 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { V(sha1su1, Sha1su1) \ V(sha256su0, Sha256su0) \ V(sha512su0, Sha512su0) \ + V(sm4e, Sm4e) \ V(smaxv, Smaxv) \ V(sminv, Sminv) \ V(sqabs, Sqabs) \ @@ -7878,6 +7918,12 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { void Umax(const Register& rd, const Register& rn, const Operand& op); void Umin(const Register& rd, const Register& rn, const Operand& op); + void Yield() { + VIXL_ASSERT(allow_macro_instructions_); + SingleEmissionCheckScope guard(this); + yield(); + } + template Literal* CreateLiteralDestroyedWithPool(T value) { return new Literal(value, @@ -8249,9 +8295,10 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface { UseScratchRegisterScope* scratch_scope); bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) { + int64_t offset = label->GetLocation() - GetCursorOffset(); + VIXL_ASSERT(IsMultiple(offset, kInstructionSize)); return !Instruction::IsValidImmPCOffset(branch_type, - label->GetLocation() - - GetCursorOffset()); + offset / kInstructionSize); } void ConfigureSimulatorCPUFeaturesHelper(const CPUFeatures& features, diff --git a/3rdparty/vixl/include/vixl/aarch64/simulator-aarch64.h b/3rdparty/vixl/include/vixl/aarch64/simulator-aarch64.h index fa530bd42d..9a2c4df2f5 100644 --- a/3rdparty/vixl/include/vixl/aarch64/simulator-aarch64.h +++ b/3rdparty/vixl/include/vixl/aarch64/simulator-aarch64.h @@ -643,7 +643,7 @@ class SimVRegister : public SimRegisterBase { class LogicPRegister { public: inline LogicPRegister( - SimPRegister& other) // NOLINT(runtime/references)(runtime/explicit) + SimPRegister& other) // NOLINT(google-runtime-references) : register_(other) {} // Set a conveniently-sized block to 16 bits as the minimum predicate length @@ -744,7 +744,7 @@ using vixl_uint128_t = std::pair; class LogicVRegister { public: inline LogicVRegister( - SimVRegister& other) // NOLINT(runtime/references)(runtime/explicit) + SimVRegister& other) // NOLINT(google-runtime-references) : register_(other) { for (size_t i = 0; i < ArrayLength(saturated_); i++) { saturated_[i] = kNotSaturated; @@ -872,10 +872,9 @@ class LogicVRegister { SetUint(vform, index, value.second); return; } - // TODO: Extend this to SVE. - VIXL_ASSERT((vform == kFormat1Q) && (index == 0)); - SetUint(kFormat2D, 0, value.second); - SetUint(kFormat2D, 1, value.first); + VIXL_ASSERT((vform == kFormat1Q) || (vform == kFormatVnQ)); + SetUint(kFormatVnD, 2 * index, value.second); + SetUint(kFormatVnD, 2 * index + 1, value.first); } void SetUintArray(VectorFormat vform, const uint64_t* src) const { @@ -1447,6 +1446,7 @@ class Simulator : public DecoderVisitor { #define DECLARE(A) virtual void Visit##A(const Instruction* instr); VISITOR_LIST_THAT_RETURN(DECLARE) + SIM_AUD_VISITOR_LIST_THAT_RETURN(DECLARE) #undef DECLARE #define DECLARE(A) \ VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr); @@ -1504,6 +1504,7 @@ class Simulator : public DecoderVisitor { void SimulateSVESaturatingMulAddHigh(const Instruction* instr); void SimulateSVESaturatingMulHighIndex(const Instruction* instr); void SimulateSVEFPConvertLong(const Instruction* instr); + void SimulateSVEPmull128(const Instruction* instr); void SimulateMatrixMul(const Instruction* instr); void SimulateSVEFPMatrixMul(const Instruction* instr); void SimulateNEONMulByElementLong(const Instruction* instr); @@ -1532,8 +1533,16 @@ class Simulator : public DecoderVisitor { void SimulateSignedMinMax(const Instruction* instr); void SimulateUnsignedMinMax(const Instruction* instr); void SimulateSHA512(const Instruction* instr); + void SimulateFPConvert(const Instruction* instr); + void SimulateFPRoundInt(const Instruction* instr); + void SimulateFPRoundIntToSize(const Instruction* instr); + void SimulateNEONRoundInt(const Instruction* instr); + void SimulateNEONRoundIntToSize(const Instruction* instr); + void SimulateNEONFPConvert(const Instruction* instr); + void SimulateNEONFP2RegMisc(const Instruction* instr); void VisitCryptoSM3(const Instruction* instr); + void VisitCryptoSM4(const Instruction* instr); // Integer register accessors. @@ -2574,6 +2583,14 @@ class Simulator : public DecoderVisitor { void PrintPWrite(int rt_code, uintptr_t address) { PrintPAccess(rt_code, "->", address); } + void PrintWriteU64(uint64_t x, uintptr_t address) { + fprintf(stream_, + "# 0x%016" PRIx64 " -> %s0x%016" PRIxPTR "%s\n", + x, + clr_memory_address, + address, + clr_normal); + } // Like Print* (above), but respect GetTraceParameters(). void LogRead(int rt_code, PrintRegisterFormat format, uintptr_t address) { @@ -2608,6 +2625,9 @@ class Simulator : public DecoderVisitor { void LogPWrite(int rt_code, uintptr_t address) { if (ShouldTraceWrites()) PrintPWrite(rt_code, address); } + void LogWriteU64(uint64_t x, uintptr_t address) { + if (ShouldTraceWrites()) PrintWriteU64(x, address); + } void LogMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) { if (ShouldTraceWrites()) PrintMemTransfer(dst, src, value); } @@ -4587,6 +4607,11 @@ class Simulator : public DecoderVisitor { int index, bool is_a); + LogicVRegister sm4(LogicVRegister dst, + const LogicVRegister& src1, + const LogicVRegister& src2, + bool is_key); + #define NEON_3VREG_LOGIC_LIST(V) \ V(addhn) \ V(addhn2) \ @@ -4883,6 +4908,12 @@ class Simulator : public DecoderVisitor { LogicVRegister fcvtxn2(VectorFormat vform, LogicVRegister dst, const LogicVRegister& src); + LogicVRegister bfcvtn(VectorFormat vform, + LogicVRegister dst, + const LogicVRegister& src); + LogicVRegister bfcvtn2(VectorFormat vform, + LogicVRegister dst, + const LogicVRegister& src); LogicVRegister fsqrt(VectorFormat vform, LogicVRegister dst, const LogicVRegister& src); @@ -5000,7 +5031,7 @@ class Simulator : public DecoderVisitor { uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly); uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly); - void SysOp_W(int op, int64_t val); + bool SysOp_W(int op, int64_t val); template T FPRecipSqrtEstimate(T op); @@ -5343,7 +5374,7 @@ class Simulator : public DecoderVisitor { std::function>; static const FormToVisitorFnMap* GetFormToVisitorFnMap(); - uint32_t form_hash_; + uint32_t form_hash_{}; static const PACKey kPACKeyIA; static const PACKey kPACKeyIB; @@ -5421,9 +5452,10 @@ class Simulator : public DecoderVisitor { // in vreg is non-zero. Clear the flag, otherwise. This is almost the opposite // operation to ExpandToSimVRegister(), except that any non-zero lane is // interpreted as true. - void ExtractFromSimVRegister(VectorFormat vform, - SimPRegister& pd, // NOLINT(runtime/references) - SimVRegister vreg); + void ExtractFromSimVRegister( + VectorFormat vform, + SimPRegister& pd, // NOLINT(google-runtime-references) + SimVRegister vreg); bool coloured_trace_; @@ -5450,6 +5482,9 @@ class Simulator : public DecoderVisitor { // A configurable size of SVE vector registers. unsigned vector_length_; + // DC ZVA enable (= 0) status and block size. + unsigned dczid_ = (0 << 4) | 4; // 2^4 words => 64-byte block size. + // Representation of memory attributes such as MTE tagging and BTI page // protection in addition to branch interceptions. MetaDataDepot meta_data_; @@ -5462,19 +5497,54 @@ class Simulator : public DecoderVisitor { // The Guarded Control Stack is represented using a vector, where the more // recently stored addresses are at higher-numbered indices. - using GuardedControlStack = std::vector; + using GuardedControlStackStorage = std::vector; + public: + struct GuardedControlStack { + GuardedControlStackStorage* ptr; + uint64_t token; + }; + + private: // The GCSManager handles the synchronisation of GCS across multiple // Simulator instances. Each Simulator has its own stack, but all share // a GCSManager instance. This allows exchanging stacks between Simulators // in a threaded application. class GCSManager { public: - // Allocate a new Guarded Control Stack and add it to the vector of stacks. + // Interface for users outside the Simulator. + + // Allocate a new Guarded Control Stack. This method returns a token, which + // uniquely identifies the GCS, and can be passed *once* to the stack + // switching instructions (GSSS*), when the stack has not been used yet. + // Later arguments to the stack switching instructions must either be + // fresh tokens, or return values from the stack switching instructions. uint64_t AllocateStack() { + GuardedControlStack gcs = AllocateStackInternal(); + return gcs.token; + } + + // Free a Guarded Control Stack based on its token. + void FreeStack(uint64_t token) { + const std::lock_guard lock(stacks_mtx_); + uint64_t gcs_index = GetGCSIndexFromToken(token); + GuardedControlStackStorage* gcsptr = stacks_[gcs_index]; + if (gcsptr == nullptr) { + VIXL_ABORT_WITH_MSG("Tried to double free GCS "); + } else { + delete gcsptr; + // To ensure other tokens remain valid, we do not remove this element + // but set it to nullptr instead. + stacks_[gcs_index] = nullptr; + } + } + + private: + // Allocate a new Guarded Control Stack and add it to the vector of stacks. + GuardedControlStack AllocateStackInternal() { const std::lock_guard lock(stacks_mtx_); - GuardedControlStack* new_stack = new GuardedControlStack; + GuardedControlStackStorage* new_stack = new GuardedControlStackStorage; uint64_t result; // Put the new stack into the first available slot. @@ -5490,42 +5560,46 @@ class Simulator : public DecoderVisitor { stacks_.push_back(new_stack); } - // Shift the index to look like a stack pointer aligned to a page. - result <<= kPageSizeLog2; + result = GetGCSTokenFromIndex(result); // Push the tagged index onto the new stack as a seal. new_stack->push_back(result + 1); - return result; + + return {new_stack, result}; } - // Free a Guarded Control Stack and set the stacks_ slot to null. - void FreeStack(uint64_t gcs) { + // Get a pointer to the GCS storage using a GCS index. + GuardedControlStackStorage* GetGCSPtr(uint64_t gcs_index) { const std::lock_guard lock(stacks_mtx_); - uint64_t gcs_index = GetGCSIndex(gcs); - GuardedControlStack* gcsptr = stacks_[gcs_index]; - if (gcsptr == nullptr) { - VIXL_ABORT_WITH_MSG("Tried to free unallocated GCS "); - } else { - delete gcsptr; - stacks_[gcs_index] = nullptr; - } + return stacks_.at(GetGCSIndexFromToken(gcs_index)); } - // Get a pointer to the GCS vector using a GCS id. - GuardedControlStack* GetGCSPtr(uint64_t gcs) const { - return stacks_[GetGCSIndex(gcs)]; + // Get an index into stacks_ given a GCS token. + static uint64_t GetGCSIndexFromToken(uint64_t token) { + return token >> kPageSizeLog2; } - private: - uint64_t GetGCSIndex(uint64_t gcs) const { return gcs >> 12; } + // Get a GCS token from an index into stacks_. + static uint64_t GetGCSTokenFromIndex(uint64_t index) { + // Shift the index to look like a stack pointer aligned to a page. + return index << kPageSizeLog2; + } - std::vector stacks_; + std::vector stacks_; std::mutex stacks_mtx_; + + friend class Simulator; }; + GuardedControlStackStorage* GetGCSStorage() { return gcs_.ptr; } + uint64_t GetGCSToken() { return gcs_.token; } + // A GCS id indicating no GCS has been allocated. static const uint64_t kGCSNoStack = kPageSize - 1; - uint64_t gcs_; + // We cache both the GCS token, and the pointer to the GCS underlying + // storage, which allows us to avoid calls into GCSManager that + // would require synchronisation. + GuardedControlStack gcs_; bool gcs_enabled_; public: @@ -5539,37 +5613,45 @@ class Simulator : public DecoderVisitor { bool IsGCSCheckEnabled() const { return gcs_enabled_; } private: - bool IsAllocatedGCS(uint64_t gcs) const { return gcs != kGCSNoStack; } void ResetGCSState() { GCSManager& m = GetGCSManager(); - if (IsAllocatedGCS(gcs_)) { - m.FreeStack(gcs_); + // This method is also called in the constructor, before we have set up the + // GCS, so the call to FreeStack must be conditional. + if (GetGCSStorage() != nullptr) { + m.FreeStack(GetGCSToken()); } - ActivateGCS(m.AllocateStack()); + ActivateGCS(m.AllocateStackInternal()); GCSPop(); // Remove seal. } - GuardedControlStack* GetGCSPtr(uint64_t gcs) { + GuardedControlStackStorage* GetGCSPtr(uint64_t gcs) { GCSManager& m = GetGCSManager(); - GuardedControlStack* result = m.GetGCSPtr(gcs); + GuardedControlStackStorage* result = m.GetGCSPtr(gcs); return result; } - GuardedControlStack* GetActiveGCSPtr() { return GetGCSPtr(gcs_); } - uint64_t ActivateGCS(uint64_t gcs) { - uint64_t outgoing_gcs = gcs_; - gcs_ = gcs; - return outgoing_gcs; + GuardedControlStack ActivateGCS(GuardedControlStack incoming) { + GuardedControlStack outgoing = gcs_; + gcs_ = incoming; + return outgoing; + } + + GuardedControlStack ActivateGCS(uint64_t token) { + GuardedControlStack incoming = {GetGCSPtr(token), token}; + GuardedControlStack outgoing = gcs_; + gcs_ = incoming; + return outgoing; } void GCSPush(uint64_t addr) { - GetActiveGCSPtr()->push_back(addr); - size_t entry = GetActiveGCSPtr()->size() - 1; + GuardedControlStackStorage* gcs = GetGCSStorage(); + gcs->push_back(addr); + size_t entry = gcs->size() - 1; LogGCS(/* is_push = */ true, addr, entry); } uint64_t GCSPop() { - GuardedControlStack* gcs = GetActiveGCSPtr(); + GuardedControlStackStorage* gcs = GetGCSStorage(); if (gcs->empty()) { return 0; } @@ -5581,7 +5663,7 @@ class Simulator : public DecoderVisitor { } uint64_t GCSPeek() { - GuardedControlStack* gcs = GetActiveGCSPtr(); + GuardedControlStackStorage* gcs = GetGCSStorage(); if (gcs->empty()) { return 0; } @@ -5590,8 +5672,8 @@ class Simulator : public DecoderVisitor { } void ReportGCSFailure(const char* msg) { + GuardedControlStackStorage* gcs = GetGCSStorage(); if (IsGCSCheckEnabled()) { - GuardedControlStack* gcs = GetActiveGCSPtr(); printf("%s", msg); if (gcs == nullptr) { printf("GCS pointer is null\n"); @@ -5604,7 +5686,7 @@ class Simulator : public DecoderVisitor { gcs->pop_back(); int index = most_recent_index - i; printf(" gcs%" PRIu64 "[%d]: 0x%016" PRIx64 "\n", - gcs_, + GCSManager::GetGCSIndexFromToken(GetGCSToken()), index, entry); } diff --git a/3rdparty/vixl/include/vixl/cpu-features.h b/3rdparty/vixl/include/vixl/cpu-features.h index 1a041f6610..93efc1195a 100644 --- a/3rdparty/vixl/include/vixl/cpu-features.h +++ b/3rdparty/vixl/include/vixl/cpu-features.h @@ -202,7 +202,8 @@ namespace vixl { V(kEBF16, "EBF16", "ebf16") \ V(kSVE_EBF16, "EBF16 (SVE)", "sveebf16") \ V(kCSSC, "CSSC", "cssc") \ - V(kGCS, "GCS", "gcs") + V(kGCS, "GCS", "gcs") \ + V(kHBC, "HBC", "hbc") // clang-format on diff --git a/3rdparty/vixl/include/vixl/utils-vixl.h b/3rdparty/vixl/include/vixl/utils-vixl.h index 40b5b2703c..8324594f31 100644 --- a/3rdparty/vixl/include/vixl/utils-vixl.h +++ b/3rdparty/vixl/include/vixl/utils-vixl.h @@ -49,7 +49,7 @@ namespace vixl { #ifdef __GNUC__ #define VIXL_HAS_DEPRECATED_WITH_MSG #elif defined(__clang__) -#if __has_extension(attribute_deprecated_with_message) +#ifdef __has_extension(attribute_deprecated_with_message) #define VIXL_HAS_DEPRECATED_WITH_MSG #endif #endif @@ -258,9 +258,22 @@ class Float16 { uint16_t rawbits_; }; -// Floating point representation. uint16_t Float16ToRawbits(Float16 value); +Float16 RawbitsToFloat16(uint16_t bits); +class BFloat16 { + public: + explicit BFloat16(float value); + BFloat16() : rawbits_(0) {} + friend uint16_t BFloat16ToRawbits(BFloat16 value); + friend BFloat16 RawbitsToBFloat16(uint16_t bits); + + protected: + uint16_t rawbits_; +}; + +uint16_t BFloat16ToRawbits(BFloat16 value); +BFloat16 RawbitsToBFloat16(uint16_t bits); uint32_t FloatToRawbits(float value); VIXL_DEPRECATED("FloatToRawbits", @@ -274,8 +287,6 @@ VIXL_DEPRECATED("DoubleToRawbits", return DoubleToRawbits(value); } -Float16 RawbitsToFloat16(uint16_t bits); - float RawbitsToFloat(uint32_t bits); VIXL_DEPRECATED("RawbitsToFloat", inline float rawbits_to_float(uint32_t bits)) { @@ -629,8 +640,8 @@ bool IsRepeatingPattern(T value) { VIXL_ASSERT(IsMultiple(sizeof(value) * kBitsPerByte, BITS)); VIXL_ASSERT(IsMultiple(BITS, 2)); VIXL_STATIC_ASSERT(BITS >= 2); -#if (defined(__x86_64__) || defined(__i386)) && \ - __clang_major__ >= 17 && __clang_major__ <= 19 +#if (defined(__x86_64__) || defined(__i386)) && __clang_major__ >= 17 && \ + __clang_major__ <= 19 // Workaround for https://github.com/llvm/llvm-project/issues/108722 unsigned hbits = BITS / 2; T midmask = (~static_cast(0) >> BITS) << hbits; @@ -1132,6 +1143,8 @@ const unsigned kFloatMantissaBits = 23; const unsigned kFloatExponentBits = 8; const unsigned kFloat16MantissaBits = 10; const unsigned kFloat16ExponentBits = 5; +const unsigned kBFloat16MantissaBits = 7; +const unsigned kBFloat16ExponentBits = kFloatExponentBits; enum FPRounding { // The first four values are encodable directly by FPCR. @@ -1388,6 +1401,16 @@ static inline float FPRoundToFloat(int64_t sign, return RawbitsToFloat(bits); } +// See FPRound for a description of this function. +static inline BFloat16 FPRoundToBFloat16(int64_t sign, + int64_t exponent, + uint64_t mantissa, + FPRounding round_mode) { + return RawbitsToBFloat16( + FPRound( + sign, exponent, mantissa, round_mode)); +} + float FPToFloat(Float16 value, UseDefaultNaN DN, bool* exception = NULL); float FPToFloat(double value, @@ -1408,6 +1431,16 @@ Float16 FPToFloat16(double value, UseDefaultNaN DN, bool* exception = NULL); +BFloat16 FPToBFloat16(float value, + FPRounding round_mode, + UseDefaultNaN DN, + bool* exception = NULL); + +BFloat16 FPToBFloat16(double value, + FPRounding round_mode, + UseDefaultNaN DN, + bool* exception = NULL); + // Like static_cast(value), but with specialisations for the Float16 type. template T StaticCastFPTo(F value) { @@ -1480,7 +1513,7 @@ constexpr uint32_t Hash(const char* str, uint32_t hash = 0) { } } -constexpr uint32_t operator"" _h(const char* x, size_t) { return Hash(x); } +constexpr uint32_t operator""_h(const char* x, size_t) { return Hash(x); } } // namespace vixl diff --git a/3rdparty/vixl/src/aarch64/assembler-aarch64.cc b/3rdparty/vixl/src/aarch64/assembler-aarch64.cc index 31d5875501..2487c8402a 100644 --- a/3rdparty/vixl/src/aarch64/assembler-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/assembler-aarch64.cc @@ -263,6 +263,10 @@ void Assembler::b(int64_t imm19, Condition cond) { Emit(B_cond | ImmCondBranch(imm19) | cond); } +void Assembler::bc(int64_t imm19, Condition cond) { + VIXL_ASSERT(CPUHas(CPUFeatures::kHBC)); + Emit(B_cond | ImmCondBranch(imm19) | (1 << 4) | cond); +} void Assembler::b(Label* label) { int64_t offset = LinkAndGetInstructionOffsetTo(label); @@ -277,6 +281,11 @@ void Assembler::b(Label* label, Condition cond) { b(static_cast(offset), cond); } +void Assembler::bc(Label* label, Condition cond) { + int64_t offset = LinkAndGetInstructionOffsetTo(label); + VIXL_ASSERT(Instruction::IsValidImmPCOffset(CondBranchType, offset)); + bc(static_cast(offset), cond); +} void Assembler::bl(int64_t imm26) { Emit(BL | ImmUncondBranch(imm26)); } @@ -3689,6 +3698,23 @@ void Assembler::fjcvtzs(const Register& rd, const VRegister& vn) { Emit(FJCVTZS | Rn(vn) | Rd(rd)); } +void Assembler::bfcvt(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kBF16)); + VIXL_ASSERT(vd.Is1H() && vn.Is1S()); + Emit(0x1e634000 | Rn(vn) | Rd(vd)); +} + +void Assembler::bfcvtn(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kBF16)); + VIXL_ASSERT(vn.Is4S() && vd.Is4H()); + Emit(0x0ea16800 | Rn(vn) | Rd(vd)); +} + +void Assembler::bfcvtn2(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kBF16)); + VIXL_ASSERT(vn.Is4S() && vd.Is8H()); + Emit(0x4ea16800 | Rn(vn) | Rd(vd)); +} void Assembler::NEONFPConvertToInt(const Register& rd, const VRegister& vn, @@ -4527,7 +4553,10 @@ void Assembler::fcmla(const VRegister& vd, VIXL_ASSERT(vd.IsVector() && AreSameFormat(vd, vn)); VIXL_ASSERT((vm.IsH() && (vd.Is8H() || vd.Is4H())) || (vm.IsS() && vd.Is4S())); - if (vd.IsLaneSizeH()) VIXL_ASSERT(CPUHas(CPUFeatures::kNEONHalf)); + if (vd.IsLaneSizeH()) { + VIXL_ASSERT(CPUHas(CPUFeatures::kNEONHalf)); + VIXL_ASSERT(vd.Is8H() || (vm_index <= 1)); + } int index_num_bits = vd.Is4S() ? 1 : 2; Emit(VFormat(vd) | Rm(vm) | NEON_FCMLA_byelement | ImmNEONHLM(vm_index, index_num_bits) | ImmRotFcmlaSca(rot) | Rn(vn) | @@ -6117,6 +6146,24 @@ void Assembler::sm3tt2b(const VRegister& vd, const VRegister& vn, const VRegiste Emit(0xce408c00 | Rd(vd) | Rn(vn) | Rm(vm) | i); } +void Assembler::sm4e(const VRegister& vd, const VRegister& vn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kNEON)); + VIXL_ASSERT(CPUHas(CPUFeatures::kSM4)); + VIXL_ASSERT(vd.Is4S() && vn.Is4S()); + + Emit(0xcec08400 | Rd(vd) | Rn(vn)); +} + +void Assembler::sm4ekey(const VRegister& vd, const VRegister& vn, const VRegister& vm) { + VIXL_ASSERT(CPUHas(CPUFeatures::kNEON)); + VIXL_ASSERT(CPUHas(CPUFeatures::kSM4)); + VIXL_ASSERT(vd.Is4S() && vn.Is4S() && vm.Is4S()); + + Emit(0xce60c800 | Rd(vd) | Rn(vn) | Rm(vm)); +} + +void Assembler::yield() { hint(YIELD); } + // Note: // For all ToImm instructions below, a difference in case // for the same letter indicates a negated bit. @@ -7161,6 +7208,7 @@ bool Assembler::CPUHas(SystemRegister sysreg) const { return CPUHas(CPUFeatures::kRNG); case FPCR: case NZCV: + case DCZID_EL0: break; } return true; diff --git a/3rdparty/vixl/src/aarch64/assembler-sve-aarch64.cc b/3rdparty/vixl/src/aarch64/assembler-sve-aarch64.cc index e99cfdcdff..f2a9f665b7 100644 --- a/3rdparty/vixl/src/aarch64/assembler-sve-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/assembler-sve-aarch64.cc @@ -7410,13 +7410,13 @@ void Assembler::pmullb(const ZRegister& zd, // size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0> VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); + VIXL_ASSERT(CPUHas(CPUFeatures::kSVEPmull128) || !zd.IsLaneSizeQ()); VIXL_ASSERT(AreSameLaneSize(zn, zm)); VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS()); VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2); - // SVEPmull128 is not supported - VIXL_ASSERT(!zd.IsLaneSizeQ()); + Instr size = zd.IsLaneSizeQ() ? 0 : SVESize(zd); - Emit(0x45006800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm)); + Emit(0x45006800 | size | Rd(zd) | Rn(zn) | Rm(zm)); } void Assembler::pmullt(const ZRegister& zd, @@ -7427,13 +7427,13 @@ void Assembler::pmullt(const ZRegister& zd, // size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0> VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); + VIXL_ASSERT(CPUHas(CPUFeatures::kSVEPmull128) || !zd.IsLaneSizeQ()); VIXL_ASSERT(AreSameLaneSize(zn, zm)); VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS()); VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2); - // SVEPmull128 is not supported - VIXL_ASSERT(!zd.IsLaneSizeQ()); + Instr size = zd.IsLaneSizeQ() ? 0 : SVESize(zd); - Emit(0x45006c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm)); + Emit(0x45006c00 | size | Rd(zd) | Rn(zn) | Rm(zm)); } void Assembler::raddhnb(const ZRegister& zd, @@ -9895,5 +9895,25 @@ void Assembler::sudot(const ZRegister& zda, Emit(0x44a01c00 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn)); } +void Assembler::bfcvt(const ZRegister& zd, + const PRegisterM& pg, + const ZRegister& zn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); + VIXL_ASSERT(CPUHas(CPUFeatures::kBF16)); + VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS()); + + Emit(0x658aa000 | Rd(zd) | PgLow8(pg) | Rn(zn)); +} + +void Assembler::bfcvtnt(const ZRegister& zd, + const PRegisterM& pg, + const ZRegister& zn) { + VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); + VIXL_ASSERT(CPUHas(CPUFeatures::kBF16)); + VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS()); + + Emit(0x648aa000 | Rd(zd) | PgLow8(pg) | Rn(zn)); +} + } // namespace aarch64 } // namespace vixl diff --git a/3rdparty/vixl/src/aarch64/cpu-aarch64.cc b/3rdparty/vixl/src/aarch64/cpu-aarch64.cc index 3b70cfcd05..edf64c5a6d 100644 --- a/3rdparty/vixl/src/aarch64/cpu-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/cpu-aarch64.cc @@ -82,6 +82,7 @@ const IDRegister::Field AA64ISAR1::kI8MM(52); const IDRegister::Field AA64ISAR2::kWFXT(0); const IDRegister::Field AA64ISAR2::kRPRES(4); const IDRegister::Field AA64ISAR2::kMOPS(16); +const IDRegister::Field AA64ISAR2::kHBC(20); const IDRegister::Field AA64ISAR2::kCSSC(52); const IDRegister::Field AA64MMFR0::kECV(60); @@ -198,6 +199,7 @@ CPUFeatures AA64ISAR2::GetCPUFeatures() const { if (Get(kWFXT) >= 2) f.Combine(CPUFeatures::kWFXT); if (Get(kRPRES) >= 1) f.Combine(CPUFeatures::kRPRES); if (Get(kMOPS) >= 1) f.Combine(CPUFeatures::kMOPS); + if (Get(kHBC) >= 1) f.Combine(CPUFeatures::kHBC); if (Get(kCSSC) >= 1) f.Combine(CPUFeatures::kCSSC); return f; } diff --git a/3rdparty/vixl/src/aarch64/cpu-features-auditor-aarch64.cc b/3rdparty/vixl/src/aarch64/cpu-features-auditor-aarch64.cc index 66d29f0ecc..cf71f9a586 100644 --- a/3rdparty/vixl/src/aarch64/cpu-features-auditor-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/cpu-features-auditor-aarch64.cc @@ -41,6 +41,111 @@ CPUFeaturesAuditor::GetFormToVisitorFnMap() { static const FormToVisitorFnMap form_to_visitor = { DEFAULT_FORM_TO_VISITOR_MAP(CPUFeaturesAuditor), SIM_AUD_VISITOR_MAP(CPUFeaturesAuditor), + {"fcvt_dh_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fcvt_ds_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fcvt_hd_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fcvt_hs_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fcvt_sd_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fcvt_sh_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fmov_d_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fmov_h_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"fmov_s_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint32x_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint32x_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint32z_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint32z_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint64x_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint64x_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint64z_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint64z_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinta_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinta_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinta_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinti_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinti_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frinti_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintm_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintm_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintm_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintn_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintn_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintn_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintp_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintp_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintp_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintx_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintx_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintx_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintz_d_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintz_h_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frintz_s_floatdp1"_h, + &CPUFeaturesAuditor::VisitFPDataProcessing1Source}, + {"frint32x_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frint32z_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frint64x_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frint64z_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frinta_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frinti_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frintm_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frintn_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frintp_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frintx_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frintz_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtas_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtau_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtl_asimdmisc_l"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtms_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtmu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtns_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtnu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtn_asimdmisc_n"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtps_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtpu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtxn_asimdmisc_n"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtzs_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcvtzu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fabs_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcmeq_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcmge_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcmgt_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcmle_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fcmlt_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fneg_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frecpe_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"frsqrte_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"fsqrt_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"scvtf_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"ucvtf_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"urecpe_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, + {"ursqrte_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc}, {"fcmla_asimdelem_c_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, {"fcmla_asimdelem_c_s"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, {"fmlal2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement}, @@ -226,6 +331,9 @@ void CPUFeaturesAuditor::VisitCompareBranch(const Instruction* instr) { void CPUFeaturesAuditor::VisitConditionalBranch(const Instruction* instr) { RecordInstructionFeaturesScope scope(this); USE(instr); + if (form_hash_ == "bc_only_condbranch"_h) { + scope.Record(CPUFeatures::kHBC); + } } void CPUFeaturesAuditor::VisitConditionalCompareImmediate( @@ -285,6 +393,12 @@ void CPUFeaturesAuditor::VisitCryptoSM3(const Instruction* instr) { USE(instr); } +void CPUFeaturesAuditor::VisitCryptoSM4(const Instruction* instr) { + RecordInstructionFeaturesScope scope(this); + scope.Record(CPUFeatures::kNEON, CPUFeatures::kSM4); + USE(instr); +} + void CPUFeaturesAuditor::VisitDataProcessing1Source(const Instruction* instr) { RecordInstructionFeaturesScope scope(this); switch (instr->Mask(DataProcessing1SourceMask)) { @@ -1876,6 +1990,18 @@ void CPUFeaturesAuditor::Visit(Metadata* metadata, const Instruction* instr) { CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kSHA512)}, {"sha512su1_vvv2_cryptosha512_3"_h, CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kSHA512)}, + {"pmullb_z_zz_q"_h, + CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEPmull128)}, + {"pmullt_z_zz_q"_h, + CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEPmull128)}, + {"bfcvt_bs_floatdp1"_h, + CPUFeatures(CPUFeatures::kFP, CPUFeatures::kBF16)}, + {"bfcvtn_asimdmisc_4s"_h, + CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kBF16)}, + {"bfcvt_z_p_z_s2bf"_h, + CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kBF16)}, + {"bfcvtnt_z_p_z_s2bf"_h, + CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kBF16)}, }; if (features.count(form_hash_) > 0) { diff --git a/3rdparty/vixl/src/aarch64/debugger-aarch64.cc b/3rdparty/vixl/src/aarch64/debugger-aarch64.cc new file mode 100644 index 0000000000..1b060fd96b --- /dev/null +++ b/3rdparty/vixl/src/aarch64/debugger-aarch64.cc @@ -0,0 +1,498 @@ +// Copyright 2023, VIXL authors +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of ARM Limited nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 + +#include "debugger-aarch64.h" + +#include +#include +#include +#include +#include + +namespace vixl { +namespace aarch64 { + + +Debugger::Debugger(Simulator* sim) + : sim_(sim), input_stream_(&std::cin), ostream_(sim->GetOutputStream()) { + // Register all basic debugger commands. + RegisterCmd(); + RegisterCmd(); + RegisterCmd(); + RegisterCmd(); + RegisterCmd(); + RegisterCmd(); + RegisterCmd(); +} + + +template +void Debugger::RegisterCmd() { + auto new_command = std::make_unique(sim_); + + // Check that the new command word and alias, don't already exist. + std::string_view new_cmd_word = new_command->GetCommandWord(); + std::string_view new_cmd_alias = new_command->GetCommandAlias(); + for (const auto& cmd : debugger_cmds_) { + std::string_view cmd_word = cmd->GetCommandWord(); + std::string_view cmd_alias = cmd->GetCommandAlias(); + + if (new_cmd_word == cmd_word) { + VIXL_ABORT_WITH_MSG("Command word matches an existing command word."); + } else if (new_cmd_word == cmd_alias) { + VIXL_ABORT_WITH_MSG("Command word matches an existing command alias."); + } + + if (new_cmd_alias != "") { + if (new_cmd_alias == cmd_word) { + VIXL_ABORT_WITH_MSG("Command alias matches an existing command word."); + } else if (new_cmd_alias == cmd_alias) { + VIXL_ABORT_WITH_MSG("Command alias matches an existing command alias."); + } + } + } + + debugger_cmds_.push_back(std::move(new_command)); +} + + +bool Debugger::IsAtBreakpoint() const { + return IsBreakpoint(reinterpret_cast(sim_->ReadPc())); +} + + +void Debugger::Debug() { + DebugReturn done = DebugContinue; + while (done == DebugContinue) { + // Disassemble the next instruction to execute. + PrintDisassembler print_disasm = PrintDisassembler(ostream_); + print_disasm.Disassemble(sim_->ReadPc()); + + // Read the command line. + fprintf(ostream_, "sim> "); + std::string line; + std::getline(*input_stream_, line); + + // Remove all control characters from the command string. + line.erase(std::remove_if(line.begin(), + line.end(), + [](char c) { return std::iscntrl(c); }), + line.end()); + + // Assume input from std::cin has already been output (e.g: by a terminal) + // but input from elsewhere (e.g: from a testing input stream) has not. + if (input_stream_ != &std::cin) { + fprintf(ostream_, "%s\n", line.c_str()); + } + + // Parse the command into tokens. + std::vector tokenized_cmd = Tokenize(line); + if (!tokenized_cmd.empty()) { + done = ExecDebugCommand(tokenized_cmd); + } + } +} + + +std::optional Debugger::ParseUint64String(std::string_view uint64_str, + int base) { + // Clear any previous errors. + errno = 0; + + // strtoull uses 0 to indicate that no conversion was possible so first + // check that the string isn't zero. + if (IsZeroUint64String(uint64_str, base)) { + return 0; + } + + // Cannot use stoi as it might not be possible to use exceptions. + char* end; + uint64_t value = std::strtoull(uint64_str.data(), &end, base); + if (value == 0 || *end != '\0' || errno == ERANGE) { + return std::nullopt; + } + + return value; +} + + +std::optional Debugger::ParseRegString( + std::string_view reg_str) { + // A register should only have 2 (e.g: X0) or 3 (e.g: X31) characters. + if (reg_str.size() < 2 || reg_str.size() > 3) { + return std::nullopt; + } + + // Check for aliases of registers. + if (reg_str == "lr") { + return {{'X', kLinkRegCode}}; + } else if (reg_str == "sp") { + return {{'X', kSpRegCode}}; + } + + unsigned max_reg_num; + char reg_prefix = std::toupper(reg_str.front()); + switch (reg_prefix) { + case 'W': + VIXL_FALLTHROUGH(); + case 'X': + max_reg_num = kNumberOfRegisters - 1; + break; + case 'V': + max_reg_num = kNumberOfVRegisters - 1; + break; + case 'Z': + max_reg_num = kNumberOfZRegisters - 1; + break; + case 'P': + max_reg_num = kNumberOfPRegisters - 1; + break; + default: + return std::nullopt; + } + + std::string_view str_code = reg_str.substr(1, reg_str.size()); + auto reg_code = ParseUint64String(str_code, 10); + if (!reg_code) { + return std::nullopt; + } + + if (*reg_code > max_reg_num) { + return std::nullopt; + } + + return {{reg_prefix, static_cast(*reg_code)}}; +} + + +void Debugger::PrintUsage() { + for (const auto& cmd : debugger_cmds_) { + // Print commands in the following format: + // foo / f + // foo + // A description of the foo command. + // + + std::string_view cmd_word = cmd->GetCommandWord(); + std::string_view cmd_alias = cmd->GetCommandAlias(); + if (cmd_alias != "") { + fprintf(ostream_, "%s / %s\n", cmd_word.data(), cmd_alias.data()); + } else { + fprintf(ostream_, "%s\n", cmd_word.data()); + } + + std::string_view args_str = cmd->GetArgsString(); + if (args_str != "") { + fprintf(ostream_, "\t%s %s\n", cmd_word.data(), args_str.data()); + } + + std::string_view description = cmd->GetDescription(); + if (description != "") { + fprintf(ostream_, "\t%s\n", description.data()); + } + } +} + + +std::vector Debugger::Tokenize(std::string_view input_line, + char separator) { + std::vector words; + + if (input_line.empty()) { + return words; + } + + for (auto separator_pos = input_line.find(separator); + separator_pos != input_line.npos; + separator_pos = input_line.find(separator)) { + // Skip consecutive, repeated separators. + if (separator_pos != 0) { + words.push_back(std::string{input_line.substr(0, separator_pos)}); + } + + // Remove characters up to and including the separator. + input_line.remove_prefix(separator_pos + 1); + } + + // Add the rest of the string to the vector. + words.push_back(std::string{input_line}); + + return words; +} + + +DebugReturn Debugger::ExecDebugCommand( + const std::vector& tokenized_cmd) { + std::string cmd_word = tokenized_cmd.front(); + for (const auto& cmd : debugger_cmds_) { + if (cmd_word == cmd->GetCommandWord() || + cmd_word == cmd->GetCommandAlias()) { + const std::vector args(tokenized_cmd.begin() + 1, + tokenized_cmd.end()); + + // Call the handler for the command and pass the arguments. + return cmd->Action(args); + } + } + + fprintf(ostream_, "Error: command '%s' not found\n", cmd_word.c_str()); + return DebugContinue; +} + + +bool Debugger::IsZeroUint64String(std::string_view uint64_str, int base) { + // Remove any hex prefixes. + if (base == 0 || base == 16) { + std::string_view prefix = uint64_str.substr(0, 2); + if (prefix == "0x" || prefix == "0X") { + uint64_str.remove_prefix(2); + } + } + + if (uint64_str.empty()) { + return false; + } + + // Check all remaining digits in the string for anything other than zero. + for (char c : uint64_str) { + if (c != '0') { + return false; + } + } + + return true; +} + + +DebuggerCmd::DebuggerCmd(Simulator* sim, + std::string cmd_word, + std::string cmd_alias, + std::string args_str, + std::string description) + : sim_(sim), + ostream_(sim->GetOutputStream()), + command_word_(cmd_word), + command_alias_(cmd_alias), + args_str_(args_str), + description_(description) {} + + +DebugReturn HelpCmd::Action(const std::vector& args) { + USE(args); + sim_->GetDebugger()->PrintUsage(); + return DebugContinue; +} + + +DebugReturn BreakCmd::Action(const std::vector& args) { + if (args.size() != 1) { + fprintf(ostream_, "Error: Use `break
` to set a breakpoint\n"); + return DebugContinue; + } + + std::string arg = args.front(); + auto break_addr = Debugger::ParseUint64String(arg); + if (!break_addr) { + fprintf(ostream_, "Error: Use `break
` to set a breakpoint\n"); + return DebugContinue; + } + + if (sim_->GetDebugger()->IsBreakpoint(*break_addr)) { + sim_->GetDebugger()->RemoveBreakpoint(*break_addr); + fprintf(ostream_, + "Breakpoint successfully removed at: 0x%" PRIx64 "\n", + *break_addr); + } else { + sim_->GetDebugger()->RegisterBreakpoint(*break_addr); + fprintf(ostream_, + "Breakpoint successfully added at: 0x%" PRIx64 "\n", + *break_addr); + } + + return DebugContinue; +} + + +DebugReturn StepCmd::Action(const std::vector& args) { + if (args.size() > 1) { + fprintf(ostream_, + "Error: use `step [number]` to step an optional number of" + " instructions\n"); + return DebugContinue; + } + + // Step 1 instruction by default. + std::optional number_of_instructions_to_execute{1}; + + if (args.size() == 1) { + // Parse the argument to step that number of instructions. + std::string arg = args.front(); + number_of_instructions_to_execute = Debugger::ParseUint64String(arg); + if (!number_of_instructions_to_execute) { + fprintf(ostream_, + "Error: use `step [number]` to step an optional number of" + " instructions\n"); + return DebugContinue; + } + } + + while (!sim_->IsSimulationFinished() && + *number_of_instructions_to_execute > 0) { + sim_->ExecuteInstruction(); + (*number_of_instructions_to_execute)--; + + // The first instruction has already been printed by Debug() so only + // enable instruction tracing after the first instruction has been + // executed. + sim_->SetTraceParameters(sim_->GetTraceParameters() | LOG_DISASM); + } + + // Disable instruction tracing after all instructions have been executed. + sim_->SetTraceParameters(sim_->GetTraceParameters() & ~LOG_DISASM); + + if (sim_->IsSimulationFinished()) { + fprintf(ostream_, + "Debugger at the end of simulation, leaving simulator...\n"); + return DebugExit; + } + + return DebugContinue; +} + + +DebugReturn ContinueCmd::Action(const std::vector& args) { + USE(args); + + fprintf(ostream_, "Continuing...\n"); + + if (sim_->GetDebugger()->IsAtBreakpoint()) { + // This breakpoint has already been hit, so execute it before continuing. + sim_->ExecuteInstruction(); + } + + return DebugExit; +} + + +DebugReturn PrintCmd::Action(const std::vector& args) { + if (args.size() != 1) { + fprintf(ostream_, + "Error: use `print ` to print the contents of a" + " specific register or all registers.\n"); + return DebugContinue; + } + + if (args.front() == "all") { + sim_->PrintRegisters(); + sim_->PrintZRegisters(); + } else if (args.front() == "system") { + sim_->PrintSystemRegisters(); + } else if (args.front() == "ffr") { + sim_->PrintFFR(); + } else { + auto reg = Debugger::ParseRegString(args.front()); + if (!reg) { + fprintf(ostream_, + "Error: incorrect register format, use e.g: X0, x0, etc...\n"); + return DebugContinue; + } + + // Ensure the stack pointer is printed instead of the zero register. + if ((*reg).second == kSpRegCode) { + (*reg).second = kSPRegInternalCode; + } + + // Registers are printed in different ways depending on their type. + switch ((*reg).first) { + case 'W': + sim_->PrintRegister( + (*reg).second, + static_cast( + Simulator::PrintRegisterFormat::kPrintWReg | + Simulator::PrintRegisterFormat::kPrintRegPartial)); + break; + case 'X': + sim_->PrintRegister((*reg).second, + Simulator::PrintRegisterFormat::kPrintXReg); + break; + case 'V': + sim_->PrintVRegister((*reg).second); + break; + case 'Z': + sim_->PrintZRegister((*reg).second); + break; + case 'P': + sim_->PrintPRegister((*reg).second); + break; + default: + // ParseRegString should only allow valid register characters. + VIXL_UNREACHABLE(); + } + } + + return DebugContinue; +} + + +DebugReturn TraceCmd::Action(const std::vector& args) { + if (args.size() != 0) { + fprintf(ostream_, "Error: use `trace` to toggle tracing of registers.\n"); + return DebugContinue; + } + + int trace_params = sim_->GetTraceParameters(); + if ((trace_params & LOG_ALL) != LOG_ALL) { + fprintf(ostream_, + "Enabling disassembly, registers and memory write tracing\n"); + sim_->SetTraceParameters(trace_params | LOG_ALL); + } else { + fprintf(ostream_, + "Disabling disassembly, registers and memory write tracing\n"); + sim_->SetTraceParameters(trace_params & ~LOG_ALL); + } + + return DebugContinue; +} + + +DebugReturn GdbCmd::Action(const std::vector& args) { + if (args.size() != 0) { + fprintf(ostream_, + "Error: use `gdb` to enter GDB from the simulator debugger.\n"); + return DebugContinue; + } + + HostBreakpoint(); + return DebugContinue; +} + + +} // namespace aarch64 +} // namespace vixl + +#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 diff --git a/3rdparty/vixl/src/aarch64/decoder-aarch64.cc b/3rdparty/vixl/src/aarch64/decoder-aarch64.cc index 4ff02c114d..01cd4a67fb 100644 --- a/3rdparty/vixl/src/aarch64/decoder-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/decoder-aarch64.cc @@ -138,11 +138,854 @@ void Decoder::VisitNamedInstruction(const Instruction* instr, const std::string& name) { std::list::iterator it; Metadata m = {{"form", name}}; + uint32_t form_hash = Hash(name.c_str()); + + // If an encoding is unallocated for this form, add the information to the + // metadata. + auto range = form_to_unalloc_.equal_range(form_hash); + for (auto itu = range.first; itu != range.second; ++itu) { + uint32_t mask = itu->second >> 32; + uint32_t value = itu->second & 0xffffffff; + if (instr->Mask(mask) == value) { + m.insert({"unallocated", ""}); + break; + } + } + for (it = visitors_.begin(); it != visitors_.end(); it++) { (*it)->Visit(&m, instr); } } +void Decoder::PopulatePerInstructionUnallocatedMap(FormToUnallocMap* ftm) { + using UnallocToFormMap = + std::unordered_map>; + + // Map from mask/value (as uint64) to instruction form. Given an encoding, + // if, after applying the bitmask (top 32 bits), the resulting encoding equals + // bottom 32 bits, then the encoding is unallocated for the instructions + // indexed by the mask/value. On object construction, this is used to build a + // map from instruction to mask/value, allowing fast lookup during + // disassembly. + static const UnallocToFormMap forms = + {{0x00000001'00000001, + {"casp_cp32_ldstexcl"_h, + "caspa_cp32_ldstexcl"_h, + "caspl_cp32_ldstexcl"_h, + "caspal_cp32_ldstexcl"_h, + "casp_cp64_ldstexcl"_h, + "caspa_cp64_ldstexcl"_h, + "caspl_cp64_ldstexcl"_h, + "caspal_cp64_ldstexcl"_h}}, + {0x0000001f'0000001f, + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h, + "seten_set_memcms"_h, "sete_set_memcms"_h, "setgen_set_memcms"_h, + "setge_set_memcms"_h, "setgmn_set_memcms"_h, "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, "setgp_set_memcms"_h, "setmn_set_memcms"_h, + "setm_set_memcms"_h, "setpn_set_memcms"_h, "setp_set_memcms"_h}}, + {0x000003e0'000003e0, + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h, + "seten_set_memcms"_h, "sete_set_memcms"_h, "setgen_set_memcms"_h, + "setge_set_memcms"_h, "setgmn_set_memcms"_h, "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, "setgp_set_memcms"_h, "setmn_set_memcms"_h, + "setm_set_memcms"_h, "setpn_set_memcms"_h, "setp_set_memcms"_h}}, + {0x00001c00'00001400, + {"add_32_addsub_ext"_h, + "add_64_addsub_ext"_h, + "subs_32s_addsub_ext"_h, + "subs_64s_addsub_ext"_h, + "sub_32_addsub_ext"_h, + "sub_64_addsub_ext"_h}}, + {0x00001800'00001800, + {"add_32_addsub_ext"_h, + "add_64_addsub_ext"_h, + "subs_32s_addsub_ext"_h, + "subs_64s_addsub_ext"_h, + "sub_32_addsub_ext"_h, + "sub_64_addsub_ext"_h}}, + {0x00010000'00010000, + {"casp_cp32_ldstexcl"_h, + "caspa_cp32_ldstexcl"_h, + "caspl_cp32_ldstexcl"_h, + "caspal_cp32_ldstexcl"_h, + "casp_cp64_ldstexcl"_h, + "caspa_cp64_ldstexcl"_h, + "caspl_cp64_ldstexcl"_h, + "caspal_cp64_ldstexcl"_h}}, + {0x000207e0'000007c0, {"and_z_zi"_h, "eor_z_zi"_h, "orr_z_zi"_h}}, + {0x000207e0'000007e0, {"and_z_zi"_h, "eor_z_zi"_h, "orr_z_zi"_h}}, + {0x00030000'00000000, {"smov_asimdins_w_w"_h}}, + {0x00070000'00000000, {"smov_asimdins_x_x"_h, "umov_asimdins_w_w"_h}}, + {0x000f0000'00000000, + {"umov_asimdins_w_w"_h, + "umov_asimdins_x_x"_h, + "dup_asimdins_dv_v"_h, + "dup_asimdins_dr_r"_h, + "ins_asimdins_iv_v"_h, + "ins_asimdins_ir_r"_h}}, + {0x001f0000'00000000, {"dup_z_zi"_h}}, + {0x001f0000'001f0000, + {"prfb_i_p_br_s"_h, "prfd_i_p_br_s"_h, "prfh_i_p_br_s"_h, + "prfw_i_p_br_s"_h, "cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, + "cpyewn_cpy_memcms"_h, "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, + "cpyfern_cpy_memcms"_h, "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, + "cpyfmn_cpy_memcms"_h, "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, + "cpyfm_cpy_memcms"_h, "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, + "cpyfpwn_cpy_memcms"_h, "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, + "cpymrn_cpy_memcms"_h, "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, + "cpypn_cpy_memcms"_h, "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, + "cpyp_cpy_memcms"_h}}, + {0x0040f800'0000f800, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x0040fc00'00007c00, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x0040fc00'0000bc00, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x0040fc00'0000dc00, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x0040fc00'0000ec00, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x0040fc00'0000f400, + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {0x00200000'00200000, {"fcmla_asimdelem_c_s"_h}}, + {0x00400000'00000000, + {"shl_asisdshf_r"_h, + "sli_asisdshf_r"_h, + "sri_asisdshf_r"_h, + "srshr_asisdshf_r"_h, + "srsra_asisdshf_r"_h, + "sshr_asisdshf_r"_h, + "ssra_asisdshf_r"_h, + "urshr_asisdshf_r"_h, + "ursra_asisdshf_r"_h, + "ushr_asisdshf_r"_h, + "usra_asisdshf_r"_h, + "pmullb_z_zz"_h, + "pmullt_z_zz"_h, + "fcvtxn_asisdmisc_n"_h, + "fcvtxn_asimdmisc_n"_h}}, + {0x00400000'00400000, {"urecpe_asimdmisc_r"_h, "ursqrte_asimdmisc_r"_h, + "cnt_asimdmisc_r"_h, "rev16_asimdmisc_r"_h, + "shrn_asimdshf_n"_h, "rshrn_asimdshf_n"_h, + "sqshrn_asimdshf_n"_h, "sqrshrn_asimdshf_n"_h, + "sqshrun_asimdshf_n"_h, "sqrshrun_asimdshf_n"_h, + "uqshrn_asimdshf_n"_h, "uqrshrn_asimdshf_n"_h, + "sshll_asimdshf_l"_h, "ushll_asimdshf_l"_h, + "sqrshrn_asisdshf_n"_h, "sqrshrun_asisdshf_n"_h, + "sqshrn_asisdshf_n"_h, "sqshrun_asisdshf_n"_h, + "uqrshrn_asisdshf_n"_h, "uqshrn_asisdshf_n"_h}}, + {0x00060000'00000000, {"flogb_z_p_z"_h}}, + {0x00580000'00000000, + {"rshrnb_z_zi"_h, "rshrnt_z_zi"_h, "shrnb_z_zi"_h, + "shrnt_z_zi"_h, "sqrshrnb_z_zi"_h, "sqrshrnt_z_zi"_h, + "sqrshrunb_z_zi"_h, "sqrshrunt_z_zi"_h, "sqshrnb_z_zi"_h, + "sqshrnt_z_zi"_h, "sqshrunb_z_zi"_h, "sqshrunt_z_zi"_h, + "uqrshrnb_z_zi"_h, "uqrshrnt_z_zi"_h, "uqshrnb_z_zi"_h, + "uqshrnt_z_zi"_h, "sshllb_z_zi"_h, "sshllt_z_zi"_h, + "ushllb_z_zi"_h, "ushllt_z_zi"_h, "sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, "sqxtunb_z_zz"_h, "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, "uqxtnt_z_zz"_h}}, + {0x00580000'00180000, + {"sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, + "sqxtunb_z_zz"_h, + "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, + "uqxtnt_z_zz"_h}}, + {0x00580000'00480000, + {"sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, + "sqxtunb_z_zz"_h, + "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, + "uqxtnt_z_zz"_h}}, + {0x00580000'00500000, + {"sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, + "sqxtunb_z_zz"_h, + "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, + "uqxtnt_z_zz"_h}}, + {0x00580000'00580000, + {"sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, + "sqxtunb_z_zz"_h, + "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, + "uqxtnt_z_zz"_h}}, + {0x00600000'00600000, + {"fmla_asimdelem_r_sd"_h, + "fmls_asimdelem_r_sd"_h, + "fmulx_asimdelem_r_sd"_h, + "fmul_asimdelem_r_sd"_h}}, + {0x00700000'00000000, + {"fcvtzs_asisdshf_c"_h, + "fcvtzu_asisdshf_c"_h, + "scvtf_asisdshf_c"_h, + "ucvtf_asisdshf_c"_h}}, + {0x00780000'00000000, + {"sqrshrn_asisdshf_n"_h, + "sqrshrun_asisdshf_n"_h, + "sqshrn_asisdshf_n"_h, + "sqshrun_asisdshf_n"_h, + "uqrshrn_asisdshf_n"_h, + "uqshrn_asisdshf_n"_h}}, + {0x00780000'00080000, + {"scvtf_asimdshf_c"_h, + "ucvtf_asimdshf_c"_h, + "fcvtzs_asimdshf_c"_h, + "fcvtzu_asimdshf_c"_h}}, + {0x00800000'00000000, + {"compact_z_p_z"_h, "sdot_z_zzz"_h, "udot_z_zzz"_h}}, + {0x00800000'00800000, + {"cnt_asimdmisc_r"_h, "rev16_asimdmisc_r"_h, "rev32_asimdmisc_r"_h}}, + {0x00c00000'00000000, + {"smlalb_z_zzz"_h, + "smlalt_z_zzz"_h, + "smlslb_z_zzz"_h, + "smlslt_z_zzz"_h, + "sqdmlalb_z_zzz"_h, + "sqdmlalbt_z_zzz"_h, + "sqdmlalt_z_zzz"_h, + "sqdmlslb_z_zzz"_h, + "sqdmlslbt_z_zzz"_h, + "sqdmlslt_z_zzz"_h, + "umlalb_z_zzz"_h, + "umlalt_z_zzz"_h, + "umlslb_z_zzz"_h, + "umlslt_z_zzz"_h, + "faddp_z_p_zz"_h, + "fmaxnmp_z_p_zz"_h, + "fmaxp_z_p_zz"_h, + "fminnmp_z_p_zz"_h, + "fminp_z_p_zz"_h, + "urecpe_z_p_z"_h, + "ursqrte_z_p_z"_h, + "saddwb_z_zz"_h, + "saddwt_z_zz"_h, + "ssubwb_z_zz"_h, + "ssubwt_z_zz"_h, + "uaddwb_z_zz"_h, + "uaddwt_z_zz"_h, + "usubwb_z_zz"_h, + "usubwt_z_zz"_h, + "sadalp_z_p_z"_h, + "uadalp_z_p_z"_h, + "sabalb_z_zzz"_h, + "sabalt_z_zzz"_h, + "sabdlb_z_zz"_h, + "sabdlt_z_zz"_h, + "saddlb_z_zz"_h, + "saddlbt_z_zz"_h, + "saddlt_z_zz"_h, + "smullb_z_zz"_h, + "smullt_z_zz"_h, + "sqdmullb_z_zz"_h, + "sqdmullt_z_zz"_h, + "ssublb_z_zz"_h, + "ssublbt_z_zz"_h, + "ssublt_z_zz"_h, + "ssubltb_z_zz"_h, + "uabalb_z_zzz"_h, + "uabalt_z_zzz"_h, + "uabdlb_z_zz"_h, + "uabdlt_z_zz"_h, + "uaddlb_z_zz"_h, + "uaddlt_z_zz"_h, + "umullb_z_zz"_h, + "umullt_z_zz"_h, + "usublb_z_zz"_h, + "usublt_z_zz"_h, + "addhnb_z_zz"_h, + "addhnt_z_zz"_h, + "raddhnb_z_zz"_h, + "raddhnt_z_zz"_h, + "rsubhnb_z_zz"_h, + "rsubhnt_z_zz"_h, + "subhnb_z_zz"_h, + "subhnt_z_zz"_h, + "cmeq_asisdsame_only"_h, + "cmge_asisdsame_only"_h, + "cmgt_asisdsame_only"_h, + "cmhi_asisdsame_only"_h, + "cmhs_asisdsame_only"_h, + "cmtst_asisdsame_only"_h, + "add_asisdsame_only"_h, + "sub_asisdsame_only"_h, + "addp_asisdpair_only"_h, + "frinta_z_p_z"_h, + "frinti_z_p_z"_h, + "frintm_z_p_z"_h, + "frintn_z_p_z"_h, + "frintp_z_p_z"_h, + "frintx_z_p_z"_h, + "frintz_z_p_z"_h, + "frecpx_z_p_z"_h, + "fsqrt_z_p_z"_h, + "frecpe_z_z"_h, + "frsqrte_z_z"_h, + "fmad_z_p_zzz"_h, + "fmla_z_p_zzz"_h, + "fmls_z_p_zzz"_h, + "fmsb_z_p_zzz"_h, + "fnmad_z_p_zzz"_h, + "fnmla_z_p_zzz"_h, + "fnmls_z_p_zzz"_h, + "fnmsb_z_p_zzz"_h, + "faddv_v_p_z"_h, + "fmaxnmv_v_p_z"_h, + "fmaxv_v_p_z"_h, + "fminnmv_v_p_z"_h, + "fminv_v_p_z"_h, + "fcmla_z_p_zzz"_h, + "fcadd_z_p_zz"_h, + "fcmeq_p_p_z0"_h, + "fcmge_p_p_z0"_h, + "fcmgt_p_p_z0"_h, + "fcmle_p_p_z0"_h, + "fcmlt_p_p_z0"_h, + "fcmne_p_p_z0"_h, + "facge_p_p_zz"_h, + "facgt_p_p_zz"_h, + "fcmeq_p_p_zz"_h, + "fcmge_p_p_zz"_h, + "fcmgt_p_p_zz"_h, + "fcmne_p_p_zz"_h, + "fcmuo_p_p_zz"_h, + "fadd_z_zz"_h, + "fmul_z_zz"_h, + "frecps_z_zz"_h, + "frsqrts_z_zz"_h, + "fsub_z_zz"_h, + "ftsmul_z_zz"_h, + "fadda_v_p_z"_h, + "sxtw_z_p_z"_h, + "uxtw_z_p_z"_h, + "sxth_z_p_z"_h, + "uxth_z_p_z"_h, + "sxtb_z_p_z"_h, + "uxtb_z_p_z"_h, + "fabs_z_p_z"_h, + "fneg_z_p_z"_h, + "sunpkhi_z_z"_h, + "sunpklo_z_z"_h, + "uunpkhi_z_z"_h, + "uunpklo_z_z"_h, + "revb_z_z"_h, + "revh_z_z"_h, + "revw_z_z"_h, + "ftssel_z_zz"_h, + "ftmad_z_zzi"_h, + "fexpa_z_z"_h, + "fabd_z_p_zz"_h, + "fadd_z_p_zz"_h, + "fdivr_z_p_zz"_h, + "fdiv_z_p_zz"_h, + "fmaxnm_z_p_zz"_h, + "fmax_z_p_zz"_h, + "fminnm_z_p_zz"_h, + "fmin_z_p_zz"_h, + "fmulx_z_p_zz"_h, + "fmul_z_p_zz"_h, + "fscale_z_p_zz"_h, + "fsubr_z_p_zz"_h, + "fsub_z_p_zz"_h, + "fadd_z_p_zs"_h, + "fmaxnm_z_p_zs"_h, + "fmax_z_p_zs"_h, + "fminnm_z_p_zs"_h, + "fmin_z_p_zs"_h, + "fmul_z_p_zs"_h, + "fsubr_z_p_zs"_h, + "fsub_z_p_zs"_h, + "abs_asisdmisc_r"_h, + "neg_asisdmisc_r"_h, + "cmeq_asisdmisc_z"_h, + "cmge_asisdmisc_z"_h, + "cmgt_asisdmisc_z"_h, + "cmle_asisdmisc_z"_h, + "cmlt_asisdmisc_z"_h, + "cdot_z_zzz"_h, + "histcnt_z_p_zz"_h, + "sdiv_z_p_zz"_h, + "sdivr_z_p_zz"_h, + "udiv_z_p_zz"_h, + "udivr_z_p_zz"_h, + "fdup_z_i"_h, + "fcpy_z_p_i"_h, + "sqdmulh_asimdsame_only"_h, + "sqrdmulh_asimdsame_only"_h, + "fcmla_asimdsame2_c"_h, + "fcadd_asimdsame2_c"_h, + "sqrdmlah_asimdsame2_only"_h, + "sqrdmlsh_asimdsame2_only"_h, + "sdot_asimdsame2_d"_h, + "udot_asimdsame2_d"_h, + "mla_asimdelem_r"_h, + "mls_asimdelem_r"_h, + "mul_asimdelem_r"_h, + "sqdmulh_asimdelem_r"_h, + "sqrdmlah_asimdelem_r"_h, + "sqrdmlsh_asimdelem_r"_h, + "sqrdmulh_asimdelem_r"_h, + "sqdmlal_asisddiff_only"_h, + "sqdmlsl_asisddiff_only"_h, + "sqdmull_asisddiff_only"_h, + "sqdmulh_asisdsame_only"_h, + "sqrdmulh_asisdsame_only"_h, + "sqrdmlah_asisdsame2_only"_h, + "sqrdmlsh_asisdsame2_only"_h, + "srshl_asisdsame_only"_h, + "urshl_asisdsame_only"_h, + "sshl_asisdsame_only"_h, + "ushl_asisdsame_only"_h, + "sqdmulh_asisdelem_r"_h, + "sqrdmlah_asisdelem_r"_h, + "sqrdmlsh_asisdelem_r"_h, + "sqrdmulh_asisdelem_r"_h, + "sqdmlal_asisdelem_l"_h, + "sqdmlsl_asisdelem_l"_h, + "sqdmull_asisdelem_l"_h, + "smlal_asimdelem_l"_h, + "smlsl_asimdelem_l"_h, + "smull_asimdelem_l"_h, + "umlal_asimdelem_l"_h, + "umlsl_asimdelem_l"_h, + "umull_asimdelem_l"_h, + "sqdmull_asimdelem_l"_h, + "sqdmlal_asimdelem_l"_h, + "sqdmlsl_asimdelem_l"_h, + "sqdmlal_asimddiff_l"_h, + "sqdmlsl_asimddiff_l"_h, + "sqdmull_asimddiff_l"_h}}, + {0x00c00300'00000000, + {"asr_z_p_zi"_h, + "asrd_z_p_zi"_h, + "lsl_z_p_zi"_h, + "lsr_z_p_zi"_h, + "sqshl_z_p_zi"_h, + "sqshlu_z_p_zi"_h, + "srshr_z_p_zi"_h, + "uqshl_z_p_zi"_h, + "urshr_z_p_zi"_h}}, + {0x00c00000'00400000, + {"urecpe_z_p_z"_h, + "ursqrte_z_p_z"_h, + "histseg_z_zz"_h, + "pmul_z_zz"_h, + "cmeq_asisdsame_only"_h, + "cmge_asisdsame_only"_h, + "cmgt_asisdsame_only"_h, + "cmhi_asisdsame_only"_h, + "cmhs_asisdsame_only"_h, + "cmtst_asisdsame_only"_h, + "add_asisdsame_only"_h, + "sub_asisdsame_only"_h, + "addp_asisdpair_only"_h, + "sxtw_z_p_z"_h, + "uxtw_z_p_z"_h, + "sxth_z_p_z"_h, + "uxth_z_p_z"_h, + "revh_z_z"_h, + "revw_z_z"_h, + "pmul_asimdsame_only"_h, + "abs_asisdmisc_r"_h, + "neg_asisdmisc_r"_h, + "cmeq_asisdmisc_z"_h, + "cmge_asisdmisc_z"_h, + "cmgt_asisdmisc_z"_h, + "cmle_asisdmisc_z"_h, + "cmlt_asisdmisc_z"_h, + "cdot_z_zzz"_h, + "histcnt_z_p_zz"_h, + "pmull_asimddiff_l"_h, + "sdot_asimdsame2_d"_h, + "udot_asimdsame2_d"_h, + "srshl_asisdsame_only"_h, + "urshl_asisdsame_only"_h, + "sshl_asisdsame_only"_h, + "ushl_asisdsame_only"_h}}, + {0x00c00000'00800000, + {"histseg_z_zz"_h, "pmul_z_zz"_h, + "cmeq_asisdsame_only"_h, "cmge_asisdsame_only"_h, + "cmgt_asisdsame_only"_h, "cmhi_asisdsame_only"_h, + "cmhs_asisdsame_only"_h, "cmtst_asisdsame_only"_h, + "add_asisdsame_only"_h, "sub_asisdsame_only"_h, + "addp_asisdpair_only"_h, "sxtw_z_p_z"_h, + "uxtw_z_p_z"_h, "revw_z_z"_h, + "pmul_asimdsame_only"_h, "abs_asisdmisc_r"_h, + "neg_asisdmisc_r"_h, "cmeq_asisdmisc_z"_h, + "cmge_asisdmisc_z"_h, "cmgt_asisdmisc_z"_h, + "cmle_asisdmisc_z"_h, "cmlt_asisdmisc_z"_h, + "match_p_p_zz"_h, "nmatch_p_p_zz"_h, + "pmull_asimddiff_l"_h, "srshl_asisdsame_only"_h, + "urshl_asisdsame_only"_h, "sshl_asisdsame_only"_h, + "ushl_asisdsame_only"_h}}, + {0x00c00000'00c00000, + {"asr_z_p_zw"_h, + "lsl_z_p_zw"_h, + "lsr_z_p_zw"_h, + "urecpe_z_p_z"_h, + "ursqrte_z_p_z"_h, + "histseg_z_zz"_h, + "pmul_z_zz"_h, + "asr_z_zw"_h, + "lsl_z_zw"_h, + "lsr_z_zw"_h, + "pmul_asimdsame_only"_h, + "match_p_p_zz"_h, + "nmatch_p_p_zz"_h, + "adds_32_addsub_shift"_h, + "adds_64_addsub_shift"_h, + "add_32_addsub_shift"_h, + "add_64_addsub_shift"_h, + "subs_32_addsub_shift"_h, + "subs_64_addsub_shift"_h, + "sub_32_addsub_shift"_h, + "sub_64_addsub_shift"_h, + "mla_asimdsame_only"_h, + "mls_asimdsame_only"_h, + "mul_asimdsame_only"_h, + "saba_asimdsame_only"_h, + "sabd_asimdsame_only"_h, + "shadd_asimdsame_only"_h, + "shsub_asimdsame_only"_h, + "smaxp_asimdsame_only"_h, + "smax_asimdsame_only"_h, + "sminp_asimdsame_only"_h, + "smin_asimdsame_only"_h, + "srhadd_asimdsame_only"_h, + "uaba_asimdsame_only"_h, + "uabd_asimdsame_only"_h, + "uhadd_asimdsame_only"_h, + "uhsub_asimdsame_only"_h, + "umaxp_asimdsame_only"_h, + "umax_asimdsame_only"_h, + "uminp_asimdsame_only"_h, + "umin_asimdsame_only"_h, + "urhadd_asimdsame_only"_h, + "sqdmulh_asimdsame_only"_h, + "sqrdmulh_asimdsame_only"_h, + "sqrdmlah_asimdsame2_only"_h, + "sqrdmlsh_asimdsame2_only"_h, + "sdot_asimdsame2_d"_h, + "udot_asimdsame2_d"_h, + "clz_asimdmisc_r"_h, + "cls_asimdmisc_r"_h, + "rev64_asimdmisc_r"_h, + "mla_asimdelem_r"_h, + "mls_asimdelem_r"_h, + "mul_asimdelem_r"_h, + "sqdmulh_asimdelem_r"_h, + "sqrdmlah_asimdelem_r"_h, + "sqrdmlsh_asimdelem_r"_h, + "sqrdmulh_asimdelem_r"_h, + "sqxtn_asisdmisc_n"_h, + "sqxtun_asisdmisc_n"_h, + "uqxtn_asisdmisc_n"_h, + "sqdmlal_asisddiff_only"_h, + "sqdmlsl_asisddiff_only"_h, + "sqdmull_asisddiff_only"_h, + "sqdmulh_asisdsame_only"_h, + "sqrdmulh_asisdsame_only"_h, + "sqrdmlah_asisdsame2_only"_h, + "sqrdmlsh_asisdsame2_only"_h, + "sqdmulh_asisdelem_r"_h, + "sqrdmlah_asisdelem_r"_h, + "sqrdmlsh_asisdelem_r"_h, + "sqrdmulh_asisdelem_r"_h, + "sqdmlal_asisdelem_l"_h, + "sqdmlsl_asisdelem_l"_h, + "sqdmull_asisdelem_l"_h, + "shll_asimdmisc_s"_h, + "xtn_asimdmisc_n"_h, + "sqxtn_asimdmisc_n"_h, + "uqxtn_asimdmisc_n"_h, + "sqxtun_asimdmisc_n"_h, + "smlal_asimdelem_l"_h, + "smlsl_asimdelem_l"_h, + "smull_asimdelem_l"_h, + "umlal_asimdelem_l"_h, + "umlsl_asimdelem_l"_h, + "umull_asimdelem_l"_h, + "sqdmull_asimdelem_l"_h, + "sqdmlal_asimdelem_l"_h, + "sqdmlsl_asimdelem_l"_h, + "saddlv_asimdall_only"_h, + "uaddlv_asimdall_only"_h, + "addv_asimdall_only"_h, + "smaxv_asimdall_only"_h, + "sminv_asimdall_only"_h, + "umaxv_asimdall_only"_h, + "uminv_asimdall_only"_h, + "sabal_asimddiff_l"_h, + "sabdl_asimddiff_l"_h, + "saddl_asimddiff_l"_h, + "smlal_asimddiff_l"_h, + "smlsl_asimddiff_l"_h, + "smull_asimddiff_l"_h, + "ssubl_asimddiff_l"_h, + "uabal_asimddiff_l"_h, + "uabdl_asimddiff_l"_h, + "uaddl_asimddiff_l"_h, + "umlal_asimddiff_l"_h, + "umlsl_asimddiff_l"_h, + "umull_asimddiff_l"_h, + "usubl_asimddiff_l"_h, + "saddw_asimddiff_w"_h, + "ssubw_asimddiff_w"_h, + "uaddw_asimddiff_w"_h, + "usubw_asimddiff_w"_h + "addhn_asimddiff_n"_h, + "raddhn_asimddiff_n"_h, + "rsubhn_asimddiff_n"_h, + "subhn_asimddiff_n"_h, + "sqdmlal_asimddiff_l"_h, + "sqdmlsl_asimddiff_l"_h, + "sqdmull_asimddiff_l"_h}}, + {0x00c02000'00002000, {"dup_z_i"_h}}, + {0x00d80000'00000000, + {"xar_z_zzi"_h, + "asr_z_zi"_h, + "lsr_z_zi"_h, + "sri_z_zzi"_h, + "srsra_z_zi"_h, + "ssra_z_zi"_h, + "ursra_z_zi"_h, + "usra_z_zi"_h, + "lsl_z_zi"_h, + "sli_z_zzi"_h}}, + {0x40000000'00000000, {"fcmla_asimdelem_c_s"_h}}, + {0x40000800'00000800, {"fcmla_asimdelem_c_h"_h}}, + {0x40000c00'00000c00, + {"ld2_asisdlse_r2"_h, + "ld2_asisdlsep_i2_i"_h, + "ld2_asisdlsep_r2_r"_h, + "st2_asisdlse_r2"_h, + "st2_asisdlsep_i2_i"_h, + "st2_asisdlsep_r2_r"_h, + "ld3_asisdlse_r3"_h, + "ld3_asisdlsep_i3_i"_h, + "ld3_asisdlsep_r3_r"_h, + "st3_asisdlse_r3"_h, + "st3_asisdlsep_i3_i"_h, + "st3_asisdlsep_r3_r"_h, + "ld4_asisdlse_r4"_h, + "ld4_asisdlsep_i4_i"_h, + "ld4_asisdlsep_r4_r"_h, + "st4_asisdlse_r4"_h, + "st4_asisdlsep_i4_i"_h, + "st4_asisdlsep_r4_r"_h}}, + {0x40004000'00004000, {"ext_asimdext_only"_h}}, + {0x400f0000'00080000, {"dup_asimdins_dv_v"_h, "dup_asimdins_dr_d"_h}}, + {0x40400000'00000000, + {"fmaxnmv_asimdall_only_sd"_h, + "fminnmv_asimdall_only_sd"_h, + "fmaxv_asimdall_only_sd"_h, + "fminv_asimdall_only_sd"_h}}, + {0x40400000'00400000, + {"fabs_asimdmisc_r"_h, "fcvtas_asimdmisc_r"_h, + "fcvtau_asimdmisc_r"_h, "fcvtms_asimdmisc_r"_h, + "fcvtmu_asimdmisc_r"_h, "fcvtns_asimdmisc_r"_h, + "fcvtnu_asimdmisc_r"_h, "fcvtps_asimdmisc_r"_h, + "fcvtpu_asimdmisc_r"_h, "fcvtzs_asimdmisc_r"_h, + "fcvtzu_asimdmisc_r"_h, "fneg_asimdmisc_r"_h, + "frecpe_asimdmisc_r"_h, "frint32x_asimdmisc_r"_h, + "frint32z_asimdmisc_r"_h, "frint64x_asimdmisc_r"_h, + "frint64z_asimdmisc_r"_h, "frinta_asimdmisc_r"_h, + "frinti_asimdmisc_r"_h, "frintm_asimdmisc_r"_h, + "frintn_asimdmisc_r"_h, "frintp_asimdmisc_r"_h, + "frintx_asimdmisc_r"_h, "frintz_asimdmisc_r"_h, + "frsqrte_asimdmisc_r"_h, "fsqrt_asimdmisc_r"_h, + "scvtf_asimdmisc_r"_h, "ucvtf_asimdmisc_r"_h, + "fmaxnmv_asimdall_only_sd"_h, "fminnmv_asimdall_only_sd"_h, + "fmaxv_asimdall_only_sd"_h, "fminv_asimdall_only_sd"_h, + "fcmeq_asimdmisc_fz"_h, "fcmge_asimdmisc_fz"_h, + "fcmgt_asimdmisc_fz"_h, "fcmle_asimdmisc_fz"_h, + "fcmlt_asimdmisc_fz"_h, "fabd_asimdsame_only"_h, + "facge_asimdsame_only"_h, "facgt_asimdsame_only"_h, + "faddp_asimdsame_only"_h, "fadd_asimdsame_only"_h, + "fcmeq_asimdsame_only"_h, "fcmge_asimdsame_only"_h, + "fcmgt_asimdsame_only"_h, "fdiv_asimdsame_only"_h, + "fmaxnmp_asimdsame_only"_h, "fmaxnm_asimdsame_only"_h, + "fmaxp_asimdsame_only"_h, "fmax_asimdsame_only"_h, + "fminnmp_asimdsame_only"_h, "fminnm_asimdsame_only"_h, + "fminp_asimdsame_only"_h, "fmin_asimdsame_only"_h, + "fmla_asimdsame_only"_h, "fmls_asimdsame_only"_h, + "fmulx_asimdsame_only"_h, "fmul_asimdsame_only"_h, + "frecps_asimdsame_only"_h, "frsqrts_asimdsame_only"_h, + "fsub_asimdsame_only"_h, "fmla_asimdelem_r_sd"_h, + "fmls_asimdelem_r_sd"_h, "fmulx_asimdelem_r_sd"_h, + "fmul_asimdelem_r_sd"_h, "sri_asimdshf_r"_h, + "srshr_asimdshf_r"_h, "srsra_asimdshf_r"_h, + "sshr_asimdshf_r"_h, "ssra_asimdshf_r"_h, + "urshr_asimdshf_r"_h, "ursra_asimdshf_r"_h, + "ushr_asimdshf_r"_h, "usra_asimdshf_r"_h, + "scvtf_asimdshf_c"_h, "ucvtf_asimdshf_c"_h, + "fcvtzs_asimdshf_c"_h, "fcvtzu_asimdshf_c"_h}}, + {0x40400000'40400000, + {"fmaxnmv_asimdall_only_sd"_h, + "fminnmv_asimdall_only_sd"_h, + "fmaxv_asimdall_only_sd"_h, + "fminv_asimdall_only_sd"_h}}, + {0x40c00000'00800000, + {"saddlv_asimdall_only"_h, + "uaddlv_asimdall_only"_h, + "addv_asimdall_only"_h, + "smaxv_asimdall_only"_h, + "sminv_asimdall_only"_h, + "umaxv_asimdall_only"_h, + "uminv_asimdall_only"_h}}, + {0x40c00000'00c00000, + {"cmeq_asimdmisc_z"_h, "cmge_asimdmisc_z"_h, + "cmgt_asimdmisc_z"_h, "cmle_asimdmisc_z"_h, + "cmlt_asimdmisc_z"_h, "addp_asimdsame_only"_h, + "add_asimdsame_only"_h, "cmeq_asimdsame_only"_h, + "cmge_asimdsame_only"_h, "cmgt_asimdsame_only"_h, + "cmhi_asimdsame_only"_h, "cmhs_asimdsame_only"_h, + "cmtst_asimdsame_only"_h, "sqadd_asimdsame_only"_h, + "sqdmulh_asimdsame_only"_h, "sqrdmulh_asimdsame_only"_h, + "sqrshl_asimdsame_only"_h, "sqshl_asimdsame_only"_h, + "sqsub_asimdsame_only"_h, "srshl_asimdsame_only"_h, + "sshl_asimdsame_only"_h, "sub_asimdsame_only"_h, + "uqadd_asimdsame_only"_h, "uqrshl_asimdsame_only"_h, + "uqshl_asimdsame_only"_h, "uqsub_asimdsame_only"_h, + "urshl_asimdsame_only"_h, "ushl_asimdsame_only"_h, + "trn1_asimdperm_only"_h, "trn2_asimdperm_only"_h, + "uzp1_asimdperm_only"_h, "uzp2_asimdperm_only"_h, + "zip1_asimdperm_only"_h, "zip2_asimdperm_only"_h, + "fcmla_asimdsame2_c"_h, "fcadd_asimdsame2_c"_h}}, + {0x80200000'00200000, + {"sbfm_64m_bitfield"_h, + "sbfm_32m_bitfield"_h, + "ubfm_32m_bitfield"_h, + "ubfm_64m_bitfield"_h, + "bfm_32m_bitfield"_h, + "bfm_64m_bitfield"_h}}, + {0x80008000'00000000, + {"scvtf_d32_float2fix"_h, + "scvtf_d64_float2fix"_h, + "scvtf_h32_float2fix"_h, + "scvtf_h64_float2fix"_h, + "scvtf_s32_float2fix"_h, + "scvtf_s64_float2fix"_h, + "ucvtf_d32_float2fix"_h, + "ucvtf_d64_float2fix"_h, + "ucvtf_h32_float2fix"_h, + "ucvtf_h64_float2fix"_h, + "ucvtf_s32_float2fix"_h, + "ucvtf_s64_float2fix"_h}}, + {0x80008000'00008000, + {"sbfm_64m_bitfield"_h, + "sbfm_32m_bitfield"_h, + "ubfm_32m_bitfield"_h, + "ubfm_64m_bitfield"_h, + "bfm_32m_bitfield"_h, + "bfm_64m_bitfield"_h}}, + {0xc0000000'40000000, + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h, + "seten_set_memcms"_h, "sete_set_memcms"_h, "setgen_set_memcms"_h, + "setge_set_memcms"_h, "setgmn_set_memcms"_h, "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, "setgp_set_memcms"_h, "setmn_set_memcms"_h, + "setm_set_memcms"_h, "setpn_set_memcms"_h, "setp_set_memcms"_h}}, + {0xc0000000'80000000, + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h, + "seten_set_memcms"_h, "sete_set_memcms"_h, "setgen_set_memcms"_h, + "setge_set_memcms"_h, "setgmn_set_memcms"_h, "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, "setgp_set_memcms"_h, "setmn_set_memcms"_h, + "setm_set_memcms"_h, "setpn_set_memcms"_h, "setp_set_memcms"_h}}, + {0xc0000000'c0000000, + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h, + "seten_set_memcms"_h, "sete_set_memcms"_h, "setgen_set_memcms"_h, + "setge_set_memcms"_h, "setgmn_set_memcms"_h, "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, "setgp_set_memcms"_h, "setmn_set_memcms"_h, + "setm_set_memcms"_h, "setpn_set_memcms"_h, "setp_set_memcms"_h}}}; + + for (auto& itm : forms) { + const std::unordered_set& s = forms.at(itm.first); + for (const uint32_t& its : s) { + ftm->insert(std::make_pair(its, itm.first)); + } + } +} + // Initialise empty vectors for sampled bits and pattern table. const std::vector DecodeNode::kEmptySampledBits; const std::vector DecodeNode::kEmptyPatternTable; @@ -190,6 +1033,7 @@ BitExtractFn DecodeNode::GetBitExtractFunctionHelper(uint32_t x, uint32_t y) { INSTANTIATE_TEMPLATE_M(00000800); INSTANTIATE_TEMPLATE_M(00000c00); INSTANTIATE_TEMPLATE_M(00000c10); + INSTANTIATE_TEMPLATE_M(00000f00); INSTANTIATE_TEMPLATE_M(00000fc0); INSTANTIATE_TEMPLATE_M(00001000); INSTANTIATE_TEMPLATE_M(00001400); @@ -324,11 +1168,13 @@ BitExtractFn DecodeNode::GetBitExtractFunctionHelper(uint32_t x, uint32_t y) { INSTANTIATE_TEMPLATE_MV(00003000, 00002000); INSTANTIATE_TEMPLATE_MV(00003000, 00003000); INSTANTIATE_TEMPLATE_MV(00003010, 00000000); + INSTANTIATE_TEMPLATE_MV(0000301f, 0000001f); INSTANTIATE_TEMPLATE_MV(00003c00, 00003c00); INSTANTIATE_TEMPLATE_MV(00040010, 00000000); INSTANTIATE_TEMPLATE_MV(00060000, 00000000); INSTANTIATE_TEMPLATE_MV(00061000, 00000000); INSTANTIATE_TEMPLATE_MV(00070000, 00030000); + INSTANTIATE_TEMPLATE_MV(0007309f, 0000001f); INSTANTIATE_TEMPLATE_MV(00073ee0, 00033060); INSTANTIATE_TEMPLATE_MV(00073f9f, 0000001f); INSTANTIATE_TEMPLATE_MV(000f0000, 00000000); diff --git a/3rdparty/vixl/src/aarch64/disasm-aarch64.cc b/3rdparty/vixl/src/aarch64/disasm-aarch64.cc index ec4dfc9edb..e9de56e278 100644 --- a/3rdparty/vixl/src/aarch64/disasm-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/disasm-aarch64.cc @@ -28,739 +28,3251 @@ #include #include +#include #include +#include namespace vixl { namespace aarch64 { +std::string Disassembler::GetMnemonicAlias(const Instruction *instr) { + // Representation of a simple condition for an alias to apply. Mask and + // post-mask value are combined into a single 64-bit field (similar to + // unallocated instruction detection elsewhere) such that an alias + // should be applied if (i & mask_value >> 32) == (mask_value & 0xffffffff). + using MaskAlias = struct { + uint64_t mask_value; + std::string alias; + }; + + // "Simple" alias detection. For each form, one or more masking tests are + // independently applied to determine if the alias is used. + using MaskAliasMap = std::unordered_map>; + + const uint64_t kAllCases = 0x00000000'00000000; + const uint64_t kRdIsZROrSP = 0x0000001f'0000001f; + const uint64_t kRnIsZROrSP = 0x000003e0'000003e0; + const uint64_t kRaIsZROrSP = 0x00007c00'00007c00; + const uint64_t kAddSubImmZero = 0x003ffc00'00000000; + const uint64_t kLogImmIsZeroLSL = 0x00c0fc00'00000000; + const uint64_t kBFMr0s7 = 0x003ffc00'00001c00; + const uint64_t kBFMr0s15 = 0x003ffc00'00003c00; + const uint64_t kBFMr0s31 = 0x003ffc00'00007c00; + const uint64_t kBFMs31 = 0x0000fc00'00007c00; + const uint64_t kBFMs63 = 0x0000fc00'0000fc00; + const uint64_t kUMOVIsS = 0x00070000'00040000; + const uint64_t kNEONQSet = 0x40000000'40000000; + const uint64_t kSHLLImmh1 = 0x003f0000'00080000; + const uint64_t kSHLLImmh2 = 0x003f0000'00100000; + const uint64_t kSHLLImmh4 = 0x003f0000'00200000; + const uint64_t kSysIsIC = 0x0007ffe0'00037520; + const uint64_t kSysIsGCSSS1 = 0x0007ffe0'00037740; + const uint64_t kSysIsGCSPUSHM = 0x0007ffe0'00037700; + const uint64_t kSyslIsGCSPOPM = 0x0007ffe0'00037720; + const uint64_t kSyslIsGCSSS2 = 0x0007ffe0'00037760; + const uint64_t kCrmIs0 = 0x00000f00'00000000; + const uint64_t kCrmIs4 = 0x00000f00'00000400; + + static const MaskAliasMap maskmap = + {{"adds_32s_addsub_imm"_h, {{kRdIsZROrSP, "cmn"}}}, + {"adds_64s_addsub_imm"_h, {{kRdIsZROrSP, "cmn"}}}, + {"subs_32s_addsub_imm"_h, {{kRdIsZROrSP, "cmp"}}}, + {"subs_64s_addsub_imm"_h, {{kRdIsZROrSP, "cmp"}}}, + {"add_32_addsub_imm"_h, + {{kRdIsZROrSP | kAddSubImmZero, "mov"}, + {kRnIsZROrSP | kAddSubImmZero, "mov"}}}, + {"add_64_addsub_imm"_h, + {{kRdIsZROrSP | kAddSubImmZero, "mov"}, + {kRnIsZROrSP | kAddSubImmZero, "mov"}}}, + {"adds_32_addsub_shift"_h, {{kRdIsZROrSP, "cmn"}}}, + {"adds_64_addsub_shift"_h, {{kRdIsZROrSP, "cmn"}}}, + {"sub_32_addsub_shift"_h, {{kRnIsZROrSP, "neg"}}}, + {"sub_64_addsub_shift"_h, {{kRnIsZROrSP, "neg"}}}, + {"subs_32_addsub_shift"_h, + {{kRdIsZROrSP, "cmp"}, {kRnIsZROrSP, "negs"}}}, + {"subs_64_addsub_shift"_h, + {{kRdIsZROrSP, "cmp"}, {kRnIsZROrSP, "negs"}}}, + {"sbc_32_addsub_carry"_h, {{kRnIsZROrSP, "ngc"}}}, + {"sbc_64_addsub_carry"_h, {{kRnIsZROrSP, "ngc"}}}, + {"sbcs_32_addsub_carry"_h, {{kRnIsZROrSP, "ngcs"}}}, + {"sbcs_64_addsub_carry"_h, {{kRnIsZROrSP, "ngcs"}}}, + {"adds_32s_addsub_ext"_h, {{kRdIsZROrSP, "cmn"}}}, + {"adds_64s_addsub_ext"_h, {{kRdIsZROrSP, "cmn"}}}, + {"subs_32s_addsub_ext"_h, {{kRdIsZROrSP, "cmp"}}}, + {"subs_64s_addsub_ext"_h, {{kRdIsZROrSP, "cmp"}}}, + {"adds_32s_addsub_ext"_h, {{kRnIsZROrSP, "add_lsl"}}}, + {"adds_64s_addsub_ext"_h, {{kRnIsZROrSP, "add_lsl"}}}, + {"subs_32s_addsub_ext"_h, {{kRnIsZROrSP, "sub_lsl"}}}, + {"subs_64s_addsub_ext"_h, {{kRnIsZROrSP, "sub_lsl"}}}, + {"add_32_addsub_ext"_h, + {{kRdIsZROrSP, "add_lsl"}, {kRnIsZROrSP, "add_lsl"}}}, + {"add_64_addsub_ext"_h, + {{kRdIsZROrSP, "add_lsl"}, {kRnIsZROrSP, "add_lsl"}}}, + {"sub_32_addsub_ext"_h, + {{kRdIsZROrSP, "sub_lsl"}, {kRnIsZROrSP, "sub_lsl"}}}, + {"sub_64_addsub_ext"_h, + {{kRdIsZROrSP, "sub_lsl"}, {kRnIsZROrSP, "sub_lsl"}}}, + {"ands_32_log_shift"_h, {{kRdIsZROrSP, "tst"}}}, + {"ands_64_log_shift"_h, {{kRdIsZROrSP, "tst"}}}, + {"orr_32_log_shift"_h, {{kRnIsZROrSP | kLogImmIsZeroLSL, "mov"}}}, + {"orr_64_log_shift"_h, {{kRnIsZROrSP | kLogImmIsZeroLSL, "mov"}}}, + {"orn_32_log_shift"_h, {{kRnIsZROrSP, "mvn"}}}, + {"orn_64_log_shift"_h, {{kRnIsZROrSP, "mvn"}}}, + {"ands_32s_log_imm"_h, {{kRdIsZROrSP, "tst"}}}, + {"ands_64s_log_imm"_h, {{kRdIsZROrSP, "tst"}}}, + {"madd_32a_dp_3src"_h, {{kRaIsZROrSP, "mul"}}}, + {"madd_64a_dp_3src"_h, {{kRaIsZROrSP, "mul"}}}, + {"msub_32a_dp_3src"_h, {{kRaIsZROrSP, "mneg"}}}, + {"msub_64a_dp_3src"_h, {{kRaIsZROrSP, "mneg"}}}, + {"smaddl_64wa_dp_3src"_h, {{kRaIsZROrSP, "smull"}}}, + {"smsubl_64wa_dp_3src"_h, {{kRaIsZROrSP, "smnegl"}}}, + {"umaddl_64wa_dp_3src"_h, {{kRaIsZROrSP, "umull"}}}, + {"umsubl_64wa_dp_3src"_h, {{kRaIsZROrSP, "umnegl"}}}, + {"asrv_32_dp_2src"_h, {{kAllCases, "asr"}}}, + {"asrv_64_dp_2src"_h, {{kAllCases, "asr"}}}, + {"lslv_32_dp_2src"_h, {{kAllCases, "lsl"}}}, + {"lslv_64_dp_2src"_h, {{kAllCases, "lsl"}}}, + {"lsrv_32_dp_2src"_h, {{kAllCases, "lsr"}}}, + {"lsrv_64_dp_2src"_h, {{kAllCases, "lsr"}}}, + {"rorv_32_dp_2src"_h, {{kAllCases, "ror"}}}, + {"rorv_64_dp_2src"_h, {{kAllCases, "ror"}}}, + {"b_only_condbranch"_h, {{kAllCases, "b.'[condb]"}}}, + {"bc_only_condbranch"_h, {{kAllCases, "bc.'[condb]"}}}, + {"not_asimdmisc_r"_h, {{kAllCases, "mvn"}}}, + {"dup_z_i"_h, {{kAllCases, "mov"}}}, + {"fdup_z_i"_h, {{kAllCases, "fmov"}}}, + {"dup_z_r"_h, {{kAllCases, "mov"}}}, + {"cpy_z_p_r"_h, {{kAllCases, "mov"}}}, + {"cpy_z_o_i"_h, {{kAllCases, "mov"}}}, + {"cpy_z_p_i"_h, {{kAllCases, "mov"}}}, + {"cpy_z_p_v"_h, {{kAllCases, "mov"}}}, + {"fcpy_z_p_i"_h, {{kAllCases, "fmov"}}}, + {"ins_asimdins_ir_r"_h, {{kAllCases, "mov"}}}, + {"ins_asimdins_iv_v"_h, {{kAllCases, "mov"}}}, + {"umov_asimdins_x_x"_h, {{kAllCases, "mov"}}}, + {"dup_asisdone_only"_h, {{kAllCases, "mov"}}}, + {"umov_asimdins_w_w"_h, {{kUMOVIsS, "mov"}}}, + {"shrn_asimdshf_n"_h, {{kNEONQSet, "shrn2"}}}, + {"rshrn_asimdshf_n"_h, {{kNEONQSet, "rshrn2"}}}, + {"sqshrn_asimdshf_n"_h, {{kNEONQSet, "sqshrn2"}}}, + {"sqrshrn_asimdshf_n"_h, {{kNEONQSet, "sqrshrn2"}}}, + {"sqshrun_asimdshf_n"_h, {{kNEONQSet, "sqshrun2"}}}, + {"sqrshrun_asimdshf_n"_h, {{kNEONQSet, "sqrshrun2"}}}, + {"uqshrn_asimdshf_n"_h, {{kNEONQSet, "uqshrn2"}}}, + {"uqrshrn_asimdshf_n"_h, {{kNEONQSet, "uqrshrn2"}}}, + {"shll_asimdmisc_s"_h, {{kNEONQSet, "shll2"}}}, + {"xtn_asimdmisc_n"_h, {{kNEONQSet, "xtn2"}}}, + {"sqxtn_asimdmisc_n"_h, {{kNEONQSet, "sqxtn2"}}}, + {"uqxtn_asimdmisc_n"_h, {{kNEONQSet, "uqxtn2"}}}, + {"sqxtun_asimdmisc_n"_h, {{kNEONQSet, "sqxtun2"}}}, + {"smlal_asimdelem_l"_h, {{kNEONQSet, "smlal2"}}}, + {"smlsl_asimdelem_l"_h, {{kNEONQSet, "smlsl2"}}}, + {"smull_asimdelem_l"_h, {{kNEONQSet, "smull2"}}}, + {"umlal_asimdelem_l"_h, {{kNEONQSet, "umlal2"}}}, + {"umlsl_asimdelem_l"_h, {{kNEONQSet, "umlsl2"}}}, + {"umull_asimdelem_l"_h, {{kNEONQSet, "umull2"}}}, + {"sqdmull_asimdelem_l"_h, {{kNEONQSet, "sqdmull2"}}}, + {"sqdmlal_asimdelem_l"_h, {{kNEONQSet, "sqdmlal2"}}}, + {"sqdmlsl_asimdelem_l"_h, {{kNEONQSet, "sqdmlsl2"}}}, + {"bfcvtn_asimdmisc_4s"_h, {{kNEONQSet, "bfcvtn2"}}}, + {"fcvtxn_asimdmisc_n"_h, {{kNEONQSet, "fcvtxn2"}}}, + {"sabal_asimddiff_l"_h, {{kNEONQSet, "sabal2"}}}, + {"sabdl_asimddiff_l"_h, {{kNEONQSet, "sabdl2"}}}, + {"saddl_asimddiff_l"_h, {{kNEONQSet, "saddl2"}}}, + {"smlal_asimddiff_l"_h, {{kNEONQSet, "smlal2"}}}, + {"smlsl_asimddiff_l"_h, {{kNEONQSet, "smlsl2"}}}, + {"smull_asimddiff_l"_h, {{kNEONQSet, "smull2"}}}, + {"ssubl_asimddiff_l"_h, {{kNEONQSet, "ssubl2"}}}, + {"uabal_asimddiff_l"_h, {{kNEONQSet, "uabal2"}}}, + {"uabdl_asimddiff_l"_h, {{kNEONQSet, "uabdl2"}}}, + {"uaddl_asimddiff_l"_h, {{kNEONQSet, "uaddl2"}}}, + {"umlal_asimddiff_l"_h, {{kNEONQSet, "umlal2"}}}, + {"umlsl_asimddiff_l"_h, {{kNEONQSet, "umlsl2"}}}, + {"umull_asimddiff_l"_h, {{kNEONQSet, "umull2"}}}, + {"usubl_asimddiff_l"_h, {{kNEONQSet, "usubl2"}}}, + {"saddw_asimddiff_w"_h, {{kNEONQSet, "saddw2"}}}, + {"ssubw_asimddiff_w"_h, {{kNEONQSet, "ssubw2"}}}, + {"uaddw_asimddiff_w"_h, {{kNEONQSet, "uaddw2"}}}, + {"usubw_asimddiff_w"_h, {{kNEONQSet, "usubw2"}}}, + {"addhn_asimddiff_n"_h, {{kNEONQSet, "addhn2"}}}, + {"raddhn_asimddiff_n"_h, {{kNEONQSet, "raddhn2"}}}, + {"rsubhn_asimddiff_n"_h, {{kNEONQSet, "rsubhn2"}}}, + {"subhn_asimddiff_n"_h, {{kNEONQSet, "subhn2"}}}, + {"sqdmlal_asimddiff_l"_h, {{kNEONQSet, "sqdmlal2"}}}, + {"sqdmlsl_asimddiff_l"_h, {{kNEONQSet, "sqdmlsl2"}}}, + {"sqdmull_asimddiff_l"_h, {{kNEONQSet, "sqdmull2"}}}, + {"pmull_asimddiff_l"_h, {{kNEONQSet, "pmull2"}}}, + {"subps_64s_dp_2src"_h, {{kRdIsZROrSP, "cmpp"}}}, + {"sbfm_32m_bitfield"_h, + {{kBFMr0s7, "sxtb"}, {kBFMr0s15, "sxth"}, {kBFMs31, "asr"}}}, + {"sbfm_64m_bitfield"_h, + {{kBFMr0s7, "sxtb"}, + {kBFMr0s15, "sxth"}, + {kBFMr0s31, "sxtw"}, + {kBFMs63, "asr"}}}, + {"ubfm_32m_bitfield"_h, + {{kBFMr0s7, "uxtb"}, {kBFMr0s15, "uxth"}, {kBFMs31, "lsr"}}}, + {"ubfm_64m_bitfield"_h, + {{kBFMr0s7, "uxtb"}, {kBFMr0s15, "uxth"}, {kBFMs63, "lsr"}}}, + {"sshll_asimdshf_l"_h, + {{kSHLLImmh1 | kNEONQSet, "sxtl2"}, + {kSHLLImmh2 | kNEONQSet, "sxtl2"}, + {kSHLLImmh4 | kNEONQSet, "sxtl2"}, + {kSHLLImmh1, "sxtl"}, + {kSHLLImmh2, "sxtl"}, + {kSHLLImmh4, "sxtl"}, + {kNEONQSet, "sshll2"}, + {kNEONQSet, "sshll2"}, + {kNEONQSet, "sshll2"}}}, + {"ushll_asimdshf_l"_h, + {{kSHLLImmh1 | kNEONQSet, "uxtl2"}, + {kSHLLImmh2 | kNEONQSet, "uxtl2"}, + {kSHLLImmh4 | kNEONQSet, "uxtl2"}, + {kSHLLImmh1, "uxtl"}, + {kSHLLImmh2, "uxtl"}, + {kSHLLImmh4, "uxtl"}, + {kNEONQSet, "ushll2"}, + {kNEONQSet, "ushll2"}, + {kNEONQSet, "ushll2"}}}, + {"fcvtl_asimdmisc_l"_h, {{kNEONQSet, "fcvtl2"}}}, + {"fcvtn_asimdmisc_n"_h, {{kNEONQSet, "fcvtn2"}}}, + {"sys_cr_systeminstrs"_h, + {{kSysIsIC, "ic"}, + {kSysIsGCSSS1, "gcsss1"}, + {kSysIsGCSPUSHM, "gcspushm"}}}, + {"sysl_rc_systeminstrs"_h, + {{kSyslIsGCSPOPM, "gcspopm"}, {kSyslIsGCSSS2, "gcsss2"}}}, + {"dsb_bo_barriers"_h, {{kCrmIs0, "ssbb"}, {kCrmIs4, "pssbb"}}}, + {"ldaddb_32_memop"_h, {{kRdIsZROrSP, "staddb"}}}, + {"ldaddh_32_memop"_h, {{kRdIsZROrSP, "staddh"}}}, + {"ldaddlb_32_memop"_h, {{kRdIsZROrSP, "staddlb"}}}, + {"ldaddlh_32_memop"_h, {{kRdIsZROrSP, "staddlh"}}}, + {"ldaddl_32_memop"_h, {{kRdIsZROrSP, "staddl"}}}, + {"ldaddl_64_memop"_h, {{kRdIsZROrSP, "staddl"}}}, + {"ldadd_32_memop"_h, {{kRdIsZROrSP, "stadd"}}}, + {"ldadd_64_memop"_h, {{kRdIsZROrSP, "stadd"}}}, + {"ldclrb_32_memop"_h, {{kRdIsZROrSP, "stclrb"}}}, + {"ldclrh_32_memop"_h, {{kRdIsZROrSP, "stclrh"}}}, + {"ldclrlb_32_memop"_h, {{kRdIsZROrSP, "stclrlb"}}}, + {"ldclrlh_32_memop"_h, {{kRdIsZROrSP, "stclrlh"}}}, + {"ldclrl_32_memop"_h, {{kRdIsZROrSP, "stclrl"}}}, + {"ldclrl_64_memop"_h, {{kRdIsZROrSP, "stclrl"}}}, + {"ldclr_32_memop"_h, {{kRdIsZROrSP, "stclr"}}}, + {"ldclr_64_memop"_h, {{kRdIsZROrSP, "stclr"}}}, + {"ldeorb_32_memop"_h, {{kRdIsZROrSP, "steorb"}}}, + {"ldeorh_32_memop"_h, {{kRdIsZROrSP, "steorh"}}}, + {"ldeorlb_32_memop"_h, {{kRdIsZROrSP, "steorlb"}}}, + {"ldeorlh_32_memop"_h, {{kRdIsZROrSP, "steorlh"}}}, + {"ldeorl_32_memop"_h, {{kRdIsZROrSP, "steorl"}}}, + {"ldeorl_64_memop"_h, {{kRdIsZROrSP, "steorl"}}}, + {"ldeor_32_memop"_h, {{kRdIsZROrSP, "steor"}}}, + {"ldeor_64_memop"_h, {{kRdIsZROrSP, "steor"}}}, + {"ldsetb_32_memop"_h, {{kRdIsZROrSP, "stsetb"}}}, + {"ldseth_32_memop"_h, {{kRdIsZROrSP, "stseth"}}}, + {"ldsetlb_32_memop"_h, {{kRdIsZROrSP, "stsetlb"}}}, + {"ldsetlh_32_memop"_h, {{kRdIsZROrSP, "stsetlh"}}}, + {"ldsetl_32_memop"_h, {{kRdIsZROrSP, "stsetl"}}}, + {"ldsetl_64_memop"_h, {{kRdIsZROrSP, "stsetl"}}}, + {"ldset_32_memop"_h, {{kRdIsZROrSP, "stset"}}}, + {"ldset_64_memop"_h, {{kRdIsZROrSP, "stset"}}}, + {"ldsmaxb_32_memop"_h, {{kRdIsZROrSP, "stsmaxb"}}}, + {"ldsmaxh_32_memop"_h, {{kRdIsZROrSP, "stsmaxh"}}}, + {"ldsmaxlb_32_memop"_h, {{kRdIsZROrSP, "stsmaxlb"}}}, + {"ldsmaxlh_32_memop"_h, {{kRdIsZROrSP, "stsmaxlh"}}}, + {"ldsmaxl_32_memop"_h, {{kRdIsZROrSP, "stsmaxl"}}}, + {"ldsmaxl_64_memop"_h, {{kRdIsZROrSP, "stsmaxl"}}}, + {"ldsmax_32_memop"_h, {{kRdIsZROrSP, "stsmax"}}}, + {"ldsmax_64_memop"_h, {{kRdIsZROrSP, "stsmax"}}}, + {"ldsminb_32_memop"_h, {{kRdIsZROrSP, "stsminb"}}}, + {"ldsminh_32_memop"_h, {{kRdIsZROrSP, "stsminh"}}}, + {"ldsminlb_32_memop"_h, {{kRdIsZROrSP, "stsminlb"}}}, + {"ldsminlh_32_memop"_h, {{kRdIsZROrSP, "stsminlh"}}}, + {"ldsminl_32_memop"_h, {{kRdIsZROrSP, "stsminl"}}}, + {"ldsminl_64_memop"_h, {{kRdIsZROrSP, "stsminl"}}}, + {"ldsmin_32_memop"_h, {{kRdIsZROrSP, "stsmin"}}}, + {"ldsmin_64_memop"_h, {{kRdIsZROrSP, "stsmin"}}}, + {"ldumaxb_32_memop"_h, {{kRdIsZROrSP, "stumaxb"}}}, + {"ldumaxh_32_memop"_h, {{kRdIsZROrSP, "stumaxh"}}}, + {"ldumaxlb_32_memop"_h, {{kRdIsZROrSP, "stumaxlb"}}}, + {"ldumaxlh_32_memop"_h, {{kRdIsZROrSP, "stumaxlh"}}}, + {"ldumaxl_32_memop"_h, {{kRdIsZROrSP, "stumaxl"}}}, + {"ldumaxl_64_memop"_h, {{kRdIsZROrSP, "stumaxl"}}}, + {"ldumax_32_memop"_h, {{kRdIsZROrSP, "stumax"}}}, + {"ldumax_64_memop"_h, {{kRdIsZROrSP, "stumax"}}}, + {"lduminb_32_memop"_h, {{kRdIsZROrSP, "stuminb"}}}, + {"lduminh_32_memop"_h, {{kRdIsZROrSP, "stuminh"}}}, + {"lduminlb_32_memop"_h, {{kRdIsZROrSP, "stuminlb"}}}, + {"lduminlh_32_memop"_h, {{kRdIsZROrSP, "stuminlh"}}}, + {"lduminl_32_memop"_h, {{kRdIsZROrSP, "stuminl"}}}, + {"lduminl_64_memop"_h, {{kRdIsZROrSP, "stuminl"}}}, + {"ldumin_32_memop"_h, {{kRdIsZROrSP, "stumin"}}}, + {"ldumin_64_memop"_h, {{kRdIsZROrSP, "stumin"}}}}; + + // "Complex" alias detection. For each form, one or more function groups are + // applied to the encoding. If ALL of the functions in a group return true + // (ie. intersection) then the alias for that group is used. + using FuncAlias = struct { + std::vector> conditions; + std::string alias; + }; + + auto RnRmAliased = [](const Instruction *i) { + return (i->GetRn() == i->GetRm()); + }; + + auto RdRmAliased = [](const Instruction *i) { + return (i->GetRd() == i->GetRm()); + }; + + auto RdRnAliased = [](const Instruction *i) { + return (i->GetRd() == i->GetRn()); + }; + + auto PnPmAliased = [](const Instruction *i) { + return (i->GetPn() == i->GetPm()); + }; + + auto PgPmAliased = [](const Instruction *i) { + return (i->ExtractBits(13, 10) == static_cast(i->GetPm())); + }; + + auto PdPmAliased = [](const Instruction *i) { + return (i->GetPd() == i->GetPm()); + }; + + auto CondNotAlNv = [](const Instruction *i) { + return (i->GetCondition() != al) && (i->GetCondition() != nv); + }; + + auto IsNotMovzMovnImmW = [this](const Instruction *i) { + return !IsMovzMovnImm(kWRegSize, i->GetImmLogical()); + }; + + auto IsNotMovzMovnImmX = [this](const Instruction *i) { + return !IsMovzMovnImm(kXRegSize, i->GetImmLogical()); + }; + + auto IsNonOnesMov = [](const Instruction *i) { + return i->GetImmMoveWide() != 0xffff; + }; + + auto IsNonZeroNoShiftMov = [](const Instruction *i) { + return i->GetImmMoveWide() || (i->GetShiftMoveWide() == 0); + }; + + auto BitfieldSLessThanR = [](const Instruction *i) { + return i->GetImmS() < i->GetImmR(); + }; + + auto BitfieldRIsSPlus1 = [](const Instruction *i) { + return i->GetImmR() == (i->GetImmS() + 1); + }; + + auto DupHasOneSetBit = [](const Instruction *i) { + return CountSetBits(i->ExtractBits(23, 22)) + + CountSetBits(i->ExtractBits(20, 16)) == + 1; + }; + + auto IsDCOperation = [](const Instruction *i) { + std::unordered_set ops = {CVAC, + CVAU, + CVAP, + CVADP, + CIVAC, + ZVA, + GVA, + GZVA, + CGVAC, + CGDVAC, + CGVAP, + CGDVAP, + CIGVAC, + CIGDVAC}; + return ops.count(i->GetSysOp()) == 1; + }; + + auto AllCases = [](const Instruction *i) { + USE(i); + return true; + }; + + using FuncAliasMap = std::unordered_map>; + static const FuncAliasMap funcmap = + {{"csinc_32_condsel"_h, + {{{RnIsZROrSP, RmIsZROrSP, CondNotAlNv}, "cset"}, + {{RnRmAliased, CondNotAlNv}, "cinc"}}}, + {"csinc_64_condsel"_h, + {{{RnIsZROrSP, RmIsZROrSP, CondNotAlNv}, "cset"}, + {{RnRmAliased, CondNotAlNv}, "cinc"}}}, + {"csinv_32_condsel"_h, + {{{RnIsZROrSP, RmIsZROrSP, CondNotAlNv}, "csetm"}, + {{RnRmAliased, CondNotAlNv}, "cinv"}}}, + {"csinv_64_condsel"_h, + {{{RnIsZROrSP, RmIsZROrSP, CondNotAlNv}, "csetm"}, + {{RnRmAliased, CondNotAlNv}, "cinv"}}}, + {"csneg_32_condsel"_h, {{{RnRmAliased, CondNotAlNv}, "cneg"}}}, + {"csneg_64_condsel"_h, {{{RnRmAliased, CondNotAlNv}, "cneg"}}}, + {"extr_32_extract"_h, {{{RnRmAliased}, "ror"}}}, + {"extr_64_extract"_h, {{{RnRmAliased}, "ror"}}}, + {"orr_32_log_imm"_h, {{{RnIsZROrSP, IsNotMovzMovnImmW}, "mov"}}}, + {"orr_64_log_imm"_h, {{{RnIsZROrSP, IsNotMovzMovnImmX}, "mov"}}}, + {"sbfm_32m_bitfield"_h, + {{{BitfieldSLessThanR}, "sbfiz"}, {{AllCases}, "sbfx"}}}, + {"sbfm_64m_bitfield"_h, + {{{BitfieldSLessThanR}, "sbfiz"}, {{AllCases}, "sbfx"}}}, + {"ubfm_32m_bitfield"_h, + {{{BitfieldRIsSPlus1}, "lsl"}, + {{BitfieldSLessThanR}, "ubfiz"}, + {{AllCases}, "ubfx"}}}, + {"ubfm_64m_bitfield"_h, + {{{BitfieldRIsSPlus1}, "lsl"}, + {{BitfieldSLessThanR}, "ubfiz"}, + {{AllCases}, "ubfx"}}}, + {"bfm_32m_bitfield"_h, + {{{BitfieldSLessThanR, RnIsZROrSP}, "bfc"}, + {{BitfieldSLessThanR}, "bfi"}, + {{AllCases}, "bfxil"}}}, + {"bfm_64m_bitfield"_h, + {{{BitfieldSLessThanR, RnIsZROrSP}, "bfc"}, + {{BitfieldSLessThanR}, "bfi"}, + {{AllCases}, "bfxil"}}}, + {"orr_asimdsame_only"_h, {{{RnRmAliased}, "mov"}}}, + {"orr_z_zz"_h, {{{RnRmAliased}, "mov"}}}, + {"sel_z_p_zz"_h, {{{RdRmAliased}, "mov"}}}, + {"ands_p_p_pp_z"_h, {{{PnPmAliased}, "movs"}}}, + {"and_p_p_pp_z"_h, {{{PnPmAliased}, "mov"}}}, + {"eors_p_p_pp_z"_h, {{{PgPmAliased}, "nots"}}}, + {"eor_p_p_pp_z"_h, {{{PgPmAliased}, "not"}}}, + {"orrs_p_p_pp_z"_h, {{{PnPmAliased, PgPmAliased}, "movs"}}}, + {"orr_p_p_pp_z"_h, {{{PnPmAliased, PgPmAliased}, "mov"}}}, + {"sel_p_p_pp"_h, {{{PdPmAliased}, "mov"}}}, + {"movz_32_movewide"_h, {{{IsNonZeroNoShiftMov}, "mov"}}}, + {"movz_64_movewide"_h, {{{IsNonZeroNoShiftMov}, "mov"}}}, + {"movn_32_movewide"_h, {{{IsNonZeroNoShiftMov, IsNonOnesMov}, "mov"}}}, + {"movn_64_movewide"_h, {{{IsNonZeroNoShiftMov}, "mov"}}}, + {"dup_z_zi"_h, {{{DupHasOneSetBit}, "mov_1"}, {{AllCases}, "mov"}}}, + {"sys_cr_systeminstrs"_h, {{{IsDCOperation}, "dc"}}}, + {"cpyen_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyern_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyewn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpye_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfen_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfern_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfewn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfe_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfmn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfmrn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfmwn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfm_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfpn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfprn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfpwn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyfp_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpymn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpymrn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpymwn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpym_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpypn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyprn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpypwn_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"cpyp_cpy_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"seten_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"sete_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setgen_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setge_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setgmn_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setgm_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setgpn_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setgp_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setmn_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setm_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setpn_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}, + {"setp_set_memcms"_h, + {{{RdRnAliased}, "unallocated"}, + {{RdRmAliased}, "unallocated"}, + {{RnRmAliased}, "unallocated"}}}}; + + // Check simple aliases. + std::string alias; + MaskAliasMap::const_iterator ita = maskmap.find(form_hash_); + if (ita != maskmap.end()) { + for (auto rule : ita->second) { + uint64_t mv = rule.mask_value; + uint32_t mask = mv >> 32; + uint32_t value = mv & 0xffffffff; + if ((mask == 0) || (instr->Mask(mask) == value)) { + alias = rule.alias; + break; + } + } + } + + // If there was no simple alias, check for a complex one. + if (alias.length() == 0) { + FuncAliasMap::const_iterator ita2 = funcmap.find(form_hash_); + if (ita2 != funcmap.end()) { + for (auto rule : ita2->second) { + bool all = true; + for (auto cond : rule.conditions) { + all = all && cond(instr); + } + if (all == true) { + alias = rule.alias; + break; + } + } + } + } + + return alias; +} + +void Disassembler::PopulateFormToStringMap(FormToStringMap *fts) { + using StringToFormMap = + std::unordered_map>; + + // Map from disassembler format string to instruction form that uses it. On + // object construction, this is used to build a map from instruction to + // disassembler string, allowing fast lookup during disassembly. + static const StringToFormMap forms = { + {"", {"autia1716_hi_hints"_h, "autiasp_hi_hints"_h, + "autiaz_hi_hints"_h, "autib1716_hi_hints"_h, + "autibsp_hi_hints"_h, "autibz_hi_hints"_h, + "axflag_m_pstate"_h, "cfinv_m_pstate"_h, + "csdb_hi_hints"_h, "dgh_hi_hints"_h, + "ssbb_only_barriers"_h, "esb_hi_hints"_h, + "isb_bi_barriers"_h, "nop_hi_hints"_h, + "pacia1716_hi_hints"_h, "paciasp_hi_hints"_h, + "paciaz_hi_hints"_h, "pacib1716_hi_hints"_h, + "pacibsp_hi_hints"_h, "pacibz_hi_hints"_h, + "sb_only_barriers"_h, "setffr_f"_h, + "sev_hi_hints"_h, "sevl_hi_hints"_h, + "wfe_hi_hints"_h, "wfi_hi_hints"_h, + "xaflag_m_pstate"_h, "xpaclri_hi_hints"_h, + "yield_hi_hints"_h, "retaa_64e_branch_reg"_h, + "retab_64e_branch_reg"_h, "ssbb_dsb_bo_barriers"_h, + "pssbb_dsb_bo_barriers"_h}}, + {"(Unallocated)", + {"unallocated_cpyen_cpy_memcms"_h, "unallocated_cpyern_cpy_memcms"_h, + "unallocated_cpyewn_cpy_memcms"_h, "unallocated_cpye_cpy_memcms"_h, + "unallocated_cpyfen_cpy_memcms"_h, "unallocated_cpyfern_cpy_memcms"_h, + "unallocated_cpyfewn_cpy_memcms"_h, "unallocated_cpyfe_cpy_memcms"_h, + "unallocated_cpyfmn_cpy_memcms"_h, "unallocated_cpyfmrn_cpy_memcms"_h, + "unallocated_cpyfmwn_cpy_memcms"_h, "unallocated_cpyfm_cpy_memcms"_h, + "unallocated_cpyfpn_cpy_memcms"_h, "unallocated_cpyfprn_cpy_memcms"_h, + "unallocated_cpyfpwn_cpy_memcms"_h, "unallocated_cpyfp_cpy_memcms"_h, + "unallocated_cpymn_cpy_memcms"_h, "unallocated_cpymrn_cpy_memcms"_h, + "unallocated_cpymwn_cpy_memcms"_h, "unallocated_cpym_cpy_memcms"_h, + "unallocated_cpypn_cpy_memcms"_h, "unallocated_cpyprn_cpy_memcms"_h, + "unallocated_cpypwn_cpy_memcms"_h, "unallocated_cpyp_cpy_memcms"_h, + "unallocated_seten_set_memcms"_h, "unallocated_sete_set_memcms"_h, + "unallocated_setgen_set_memcms"_h, "unallocated_setge_set_memcms"_h, + "unallocated_setgmn_set_memcms"_h, "unallocated_setgm_set_memcms"_h, + "unallocated_setgpn_set_memcms"_h, "unallocated_setgp_set_memcms"_h, + "unallocated_setmn_set_memcms"_h, "unallocated_setm_set_memcms"_h, + "unallocated_setpn_set_memcms"_h, "unallocated_setp_set_memcms"_h}}, + {"['Xd]!, ['Xs]!, 'Xn!", + {"cpyen_cpy_memcms"_h, "cpyern_cpy_memcms"_h, "cpyewn_cpy_memcms"_h, + "cpye_cpy_memcms"_h, "cpyfen_cpy_memcms"_h, "cpyfern_cpy_memcms"_h, + "cpyfewn_cpy_memcms"_h, "cpyfe_cpy_memcms"_h, "cpyfmn_cpy_memcms"_h, + "cpyfmrn_cpy_memcms"_h, "cpyfmwn_cpy_memcms"_h, "cpyfm_cpy_memcms"_h, + "cpyfpn_cpy_memcms"_h, "cpyfprn_cpy_memcms"_h, "cpyfpwn_cpy_memcms"_h, + "cpyfp_cpy_memcms"_h, "cpymn_cpy_memcms"_h, "cpymrn_cpy_memcms"_h, + "cpymwn_cpy_memcms"_h, "cpym_cpy_memcms"_h, "cpypn_cpy_memcms"_h, + "cpyprn_cpy_memcms"_h, "cpypwn_cpy_memcms"_h, "cpyp_cpy_memcms"_h}}, + {"['Xd]!, 'Xn!, 'Xs", + {"seten_set_memcms"_h, + "sete_set_memcms"_h, + "setgen_set_memcms"_h, + "setge_set_memcms"_h, + "setgmn_set_memcms"_h, + "setgm_set_memcms"_h, + "setgpn_set_memcms"_h, + "setgp_set_memcms"_h, + "setmn_set_memcms"_h, + "setm_set_memcms"_h, + "setpn_set_memcms"_h, + "setp_set_memcms"_h}}, + {"#'u1105", {"hint_hm_hints"_h}}, + {"#'u1816, C'u1512, C'u1108, #'u0705'(0400=31?:, 'Xt)", + {"sys_cr_systeminstrs"_h}}, + {"#0x'x2005", + {"brk_ex_exception"_h, + "hlt_ex_exception"_h, + "hvc_ex_exception"_h, + "smc_ex_exception"_h, + "svc_ex_exception"_h}}, + {"'{dcop}, 'Xt", {"dc_sys_cr_systeminstrs"_h}}, + {"'[barrier]", {"dsb_bo_barriers"_h, "dmb_bo_barriers"_h}}, + {"'[sz]'u0400, '[sz]'u0905", + {"sqabs_asisdmisc_r"_h, + "sqneg_asisdmisc_r"_h, + "suqadd_asisdmisc_r"_h, + "usqadd_asisdmisc_r"_h}}, + {"'[sz]'u0400, '[nscall]'u0905", + {"sqxtn_asisdmisc_n"_h, "sqxtun_asisdmisc_n"_h, "uqxtn_asisdmisc_n"_h}}, + {"'[sz]'u0400, '[sz]'u0905, '[sz]'u2016", + {"sqadd_asisdsame_only"_h, + "sqdmulh_asisdsame_only"_h, + "sqrdmulh_asisdsame_only"_h, + "sqrshl_asisdsame_only"_h, + "sqshl_asisdsame_only"_h, + "sqsub_asisdsame_only"_h, + "srshl_asisdsame_only"_h, + "sshl_asisdsame_only"_h, + "uqadd_asisdsame_only"_h, + "uqrshl_asisdsame_only"_h, + "uqshl_asisdsame_only"_h, + "uqsub_asisdsame_only"_h, + "urshl_asisdsame_only"_h, + "ushl_asisdsame_only"_h, + "sqrdmlah_asisdsame2_only"_h, + "sqrdmlsh_asisdsame2_only"_h}}, + {"'[sz]'u0400, '[sz]'u0905, 'Vf.'[sz][']", + {"sqdmulh_asisdelem_r"_h, + "sqrdmlah_asisdelem_r"_h, + "sqrdmlsh_asisdelem_r"_h, + "sqrdmulh_asisdelem_r"_h}}, + {"'[sz]'u0400, 'Vn.'[n]", + {"addv_asimdall_only"_h, + "smaxv_asimdall_only"_h, + "sminv_asimdall_only"_h, + "umaxv_asimdall_only"_h, + "uminv_asimdall_only"_h}}, + {"'[nscall]'u0400, 'Vn.'[n]", + {"saddlv_asimdall_only"_h, "uaddlv_asimdall_only"_h}}, + {"'[nscall]'u0400, '[sz]'u0905, '[sz]'u2016", + {"sqdmlal_asisddiff_only"_h, + "sqdmlsl_asisddiff_only"_h, + "sqdmull_asisddiff_only"_h}}, + {"'[nscall]'u0400, '[sz]'u0905, 'Vf.'[sz][']", + {"sqdmlal_asisdelem_l"_h, + "sqdmlsl_asisdelem_l"_h, + "sqdmull_asisdelem_l"_h}}, + {"'[nshiftscal]'u0400, '[nshiftscal]'u0905, #'", + {"sqshlu_asisdshf_r"_h, "sqshl_asisdshf_r"_h, "uqshl_asisdshf_r"_h}}, + {"'[nshiftscal]'u0400, '[nshiftscal]'u0905, #'<16 31 u2219 clz32 - lsl " + "u2216 ->", + {"fcvtzs_asisdshf_c"_h, + "fcvtzu_asisdshf_c"_h, + "scvtf_asisdshf_c"_h, + "ucvtf_asisdshf_c"_h}}, + {"'[ntriscal]'u0400, 'Vn.'[ntriscal][']", + {"mov_dup_asisdone_only"_h}}, + {"'(0400=31?:'Xt)", {"gcspopm_sysl_rc_systeminstrs"_h}}, + {"'(07?j)'(06?c)", {"bti_hb_hints"_h}}, + {"'(0905=30?:'Xn)", {"ret_64r_branch_reg"_h}}, + {"'(1108=15?:#0x'x1108)", {"clrex_bn_barriers"_h}}, + {"'(21?s:'?20:hb)'u0400, '(21?d:'?20:sh)'u0905, #'<16 31 u2219 clz32 - " + "lsl u2216 ->", + {"sqrshrn_asisdshf_n"_h, + "sqrshrun_asisdshf_n"_h, + "sqshrn_asisdshf_n"_h, + "sqshrun_asisdshf_n"_h, + "uqrshrn_asisdshf_n"_h, + "uqshrn_asisdshf_n"_h}}, + {"'(2322=3?'Xd:'Wd), 'Pgl, '(2322=3?'Xd:'Wd), 'Zn.'[sz]", + {"clasta_r_p_z"_h, "clastb_r_p_z"_h}}, + {"'(2322=3?'Xd:'Wd), 'Pgl, 'Zn.'[sz]", + {"lasta_r_p_z"_h, "lastb_r_p_z"_h}}, + {"'Wt, ['Xns]", {"ldaprb_32l_memop"_h, "ldaprh_32l_memop"_h, + "ldapr_32l_memop"_h, "ldarb_lr32_ldstexcl"_h, + "ldarh_lr32_ldstexcl"_h, "ldar_lr32_ldstexcl"_h, + "ldaxrb_lr32_ldstexcl"_h, "ldaxrh_lr32_ldstexcl"_h, + "ldaxr_lr32_ldstexcl"_h, "ldlarb_lr32_ldstexcl"_h, + "ldlarh_lr32_ldstexcl"_h, "ldlar_lr32_ldstexcl"_h, + "ldxrb_lr32_ldstexcl"_h, "ldxrh_lr32_ldstexcl"_h, + "ldxr_lr32_ldstexcl"_h, "stllrb_sl32_ldstexcl"_h, + "stllrh_sl32_ldstexcl"_h, "stllr_sl32_ldstexcl"_h, + "stlrb_sl32_ldstexcl"_h, "stlrh_sl32_ldstexcl"_h, + "stlr_sl32_ldstexcl"_h}}, + {"'Xt, ['Xns]", + {"ldapr_64l_memop"_h, + "ldxr_lr64_ldstexcl"_h, + "ldaxr_lr64_ldstexcl"_h, + "ldar_lr64_ldstexcl"_h, + "ldlar_lr64_ldstexcl"_h, + "stlr_sl64_ldstexcl"_h, + "stllr_sl64_ldstexcl"_h}}, + {"'Ws, ['Xns]", + {"staddb_ldaddb_32_memop"_h, "staddh_ldaddh_32_memop"_h, + "staddlb_ldaddlb_32_memop"_h, "staddlh_ldaddlh_32_memop"_h, + "staddl_ldaddl_32_memop"_h, "stadd_ldadd_32_memop"_h, + "stclrb_ldclrb_32_memop"_h, "stclrh_ldclrh_32_memop"_h, + "stclrlb_ldclrlb_32_memop"_h, "stclrlh_ldclrlh_32_memop"_h, + "stclrl_ldclrl_32_memop"_h, "stclr_ldclr_32_memop"_h, + "steorb_ldeorb_32_memop"_h, "steorh_ldeorh_32_memop"_h, + "steorlb_ldeorlb_32_memop"_h, "steorlh_ldeorlh_32_memop"_h, + "steorl_ldeorl_32_memop"_h, "steor_ldeor_32_memop"_h, + "stsetb_ldsetb_32_memop"_h, "stseth_ldseth_32_memop"_h, + "stsetlb_ldsetlb_32_memop"_h, "stsetlh_ldsetlh_32_memop"_h, + "stsetl_ldsetl_32_memop"_h, "stset_ldset_32_memop"_h, + "stsmaxb_ldsmaxb_32_memop"_h, "stsmaxh_ldsmaxh_32_memop"_h, + "stsmaxlb_ldsmaxlb_32_memop"_h, "stsmaxlh_ldsmaxlh_32_memop"_h, + "stsmaxl_ldsmaxl_32_memop"_h, "stsmax_ldsmax_32_memop"_h, + "stsminb_ldsminb_32_memop"_h, "stsminh_ldsminh_32_memop"_h, + "stsminlb_ldsminlb_32_memop"_h, "stsminlh_ldsminlh_32_memop"_h, + "stsminl_ldsminl_32_memop"_h, "stsmin_ldsmin_32_memop"_h, + "stumaxb_ldumaxb_32_memop"_h, "stumaxh_ldumaxh_32_memop"_h, + "stumaxlb_ldumaxlb_32_memop"_h, "stumaxlh_ldumaxlh_32_memop"_h, + "stumaxl_ldumaxl_32_memop"_h, "stumax_ldumax_32_memop"_h, + "stuminb_lduminb_32_memop"_h, "stuminh_lduminh_32_memop"_h, + "stuminlb_lduminlb_32_memop"_h, "stuminlh_lduminlh_32_memop"_h, + "stuminl_lduminl_32_memop"_h, "stumin_ldumin_32_memop"_h}}, + {"'Xs, ['Xns]", + {"staddl_ldaddl_64_memop"_h, + "stadd_ldadd_64_memop"_h, + "stclrl_ldclrl_64_memop"_h, + "stclr_ldclr_64_memop"_h, + "steorl_ldeorl_64_memop"_h, + "steor_ldeor_64_memop"_h, + "stsetl_ldsetl_64_memop"_h, + "stset_ldset_64_memop"_h, + "stsmaxl_ldsmaxl_64_memop"_h, + "stsmax_ldsmax_64_memop"_h, + "stsminl_ldsminl_64_memop"_h, + "stsmin_ldsmin_64_memop"_h, + "stumaxl_ldumaxl_64_memop"_h, + "stumax_ldumax_64_memop"_h, + "stuminl_lduminl_64_memop"_h, + "stumin_ldumin_64_memop"_h}}, + {"'Ws, 'Ws+, 'Wt, 'Wt+, ['Xns]", + {"casp_cp32_ldstexcl"_h, + "caspa_cp32_ldstexcl"_h, + "caspl_cp32_ldstexcl"_h, + "caspal_cp32_ldstexcl"_h}}, + {"'Ws, 'Wt, 'Wt2, ['Xns]", + {"stxp_sp32_ldstexcl"_h, "stlxp_sp32_ldstexcl"_h}}, + {"'Ws, 'Wt, ['Xns]", {"ldaddab_32_memop"_h, "ldaddah_32_memop"_h, + "ldaddalb_32_memop"_h, "ldaddalh_32_memop"_h, + "ldaddal_32_memop"_h, "ldadda_32_memop"_h, + "ldaddb_32_memop"_h, "ldaddh_32_memop"_h, + "ldaddlb_32_memop"_h, "ldaddlh_32_memop"_h, + "ldaddl_32_memop"_h, "ldadd_32_memop"_h, + "ldclrab_32_memop"_h, "ldclrah_32_memop"_h, + "ldclralb_32_memop"_h, "ldclralh_32_memop"_h, + "ldclral_32_memop"_h, "ldclra_32_memop"_h, + "ldclrb_32_memop"_h, "ldclrh_32_memop"_h, + "ldclrlb_32_memop"_h, "ldclrlh_32_memop"_h, + "ldclrl_32_memop"_h, "ldclr_32_memop"_h, + "ldeorab_32_memop"_h, "ldeorah_32_memop"_h, + "ldeoralb_32_memop"_h, "ldeoralh_32_memop"_h, + "ldeoral_32_memop"_h, "ldeora_32_memop"_h, + "ldeorb_32_memop"_h, "ldeorh_32_memop"_h, + "ldeorlb_32_memop"_h, "ldeorlh_32_memop"_h, + "ldeorl_32_memop"_h, "ldeor_32_memop"_h, + "ldsetab_32_memop"_h, "ldsetah_32_memop"_h, + "ldsetalb_32_memop"_h, "ldsetalh_32_memop"_h, + "ldsetal_32_memop"_h, "ldseta_32_memop"_h, + "ldsetb_32_memop"_h, "ldseth_32_memop"_h, + "ldsetlb_32_memop"_h, "ldsetlh_32_memop"_h, + "ldsetl_32_memop"_h, "ldset_32_memop"_h, + "ldsmaxab_32_memop"_h, "ldsmaxah_32_memop"_h, + "ldsmaxalb_32_memop"_h, "ldsmaxalh_32_memop"_h, + "ldsmaxal_32_memop"_h, "ldsmaxa_32_memop"_h, + "ldsmaxb_32_memop"_h, "ldsmaxh_32_memop"_h, + "ldsmaxlb_32_memop"_h, "ldsmaxlh_32_memop"_h, + "ldsmaxl_32_memop"_h, "ldsmax_32_memop"_h, + "ldsminab_32_memop"_h, "ldsminah_32_memop"_h, + "ldsminalb_32_memop"_h, "ldsminalh_32_memop"_h, + "ldsminal_32_memop"_h, "ldsmina_32_memop"_h, + "ldsminb_32_memop"_h, "ldsminh_32_memop"_h, + "ldsminlb_32_memop"_h, "ldsminlh_32_memop"_h, + "ldsminl_32_memop"_h, "ldsmin_32_memop"_h, + "ldumaxab_32_memop"_h, "ldumaxah_32_memop"_h, + "ldumaxalb_32_memop"_h, "ldumaxalh_32_memop"_h, + "ldumaxal_32_memop"_h, "ldumaxa_32_memop"_h, + "ldumaxb_32_memop"_h, "ldumaxh_32_memop"_h, + "ldumaxlb_32_memop"_h, "ldumaxlh_32_memop"_h, + "ldumaxl_32_memop"_h, "ldumax_32_memop"_h, + "lduminab_32_memop"_h, "lduminah_32_memop"_h, + "lduminalb_32_memop"_h, "lduminalh_32_memop"_h, + "lduminal_32_memop"_h, "ldumina_32_memop"_h, + "lduminb_32_memop"_h, "lduminh_32_memop"_h, + "lduminlb_32_memop"_h, "lduminlh_32_memop"_h, + "lduminl_32_memop"_h, "ldumin_32_memop"_h, + "swpab_32_memop"_h, "swpah_32_memop"_h, + "swpalb_32_memop"_h, "swpalh_32_memop"_h, + "swpal_32_memop"_h, "swpa_32_memop"_h, + "swpb_32_memop"_h, "swph_32_memop"_h, + "swplb_32_memop"_h, "swplh_32_memop"_h, + "swpl_32_memop"_h, "swp_32_memop"_h, + "cas_c32_ldstexcl"_h, "casa_c32_ldstexcl"_h, + "casl_c32_ldstexcl"_h, "casal_c32_ldstexcl"_h, + "casb_c32_ldstexcl"_h, "casab_c32_ldstexcl"_h, + "caslb_c32_ldstexcl"_h, "casalb_c32_ldstexcl"_h, + "cash_c32_ldstexcl"_h, "casah_c32_ldstexcl"_h, + "caslh_c32_ldstexcl"_h, "casalh_c32_ldstexcl"_h, + "stxrb_sr32_ldstexcl"_h, "stxrh_sr32_ldstexcl"_h, + "stxr_sr32_ldstexcl"_h, "stlxrb_sr32_ldstexcl"_h, + "stlxrh_sr32_ldstexcl"_h, "stlxr_sr32_ldstexcl"_h}}, + {"'Ws, 'Xt, 'Xt2, ['Xns]", + {"stxp_sp64_ldstexcl"_h, "stlxp_sp64_ldstexcl"_h}}, + {"'Ws, 'Xt, ['Xns]", {"stxr_sr64_ldstexcl"_h, "stlxr_sr64_ldstexcl"_h}}, + {"'Xs, 'Xs+, 'Xt, 'Xt+, ['Xns]", + {"casp_cp64_ldstexcl"_h, + "caspa_cp64_ldstexcl"_h, + "caspl_cp64_ldstexcl"_h, + "caspal_cp64_ldstexcl"_h}}, + {"'Xs, 'Xt, ['Xns]", + {"ldaddal_64_memop"_h, "ldadda_64_memop"_h, "ldaddl_64_memop"_h, + "ldadd_64_memop"_h, "ldclral_64_memop"_h, "ldclra_64_memop"_h, + "ldclrl_64_memop"_h, "ldclr_64_memop"_h, "ldeoral_64_memop"_h, + "ldeora_64_memop"_h, "ldeorl_64_memop"_h, "ldeor_64_memop"_h, + "ldsetal_64_memop"_h, "ldseta_64_memop"_h, "ldsetl_64_memop"_h, + "ldset_64_memop"_h, "ldsmaxal_64_memop"_h, "ldsmaxa_64_memop"_h, + "ldsmaxl_64_memop"_h, "ldsmax_64_memop"_h, "ldsminal_64_memop"_h, + "ldsmina_64_memop"_h, "ldsminl_64_memop"_h, "ldsmin_64_memop"_h, + "ldumaxal_64_memop"_h, "ldumaxa_64_memop"_h, "ldumaxl_64_memop"_h, + "ldumax_64_memop"_h, "lduminal_64_memop"_h, "ldumina_64_memop"_h, + "lduminl_64_memop"_h, "ldumin_64_memop"_h, "swpal_64_memop"_h, + "swpa_64_memop"_h, "swpl_64_memop"_h, "swp_64_memop"_h, + "cas_c64_ldstexcl"_h, "casa_c64_ldstexcl"_h, "casl_c64_ldstexcl"_h, + "casal_c64_ldstexcl"_h}}, + {"'?22:ds'u0400, '?22:ds'u0905", + {"fcvtas_asisdmisc_r"_h, + "fcvtau_asisdmisc_r"_h, + "fcvtms_asisdmisc_r"_h, + "fcvtmu_asisdmisc_r"_h, + "fcvtns_asisdmisc_r"_h, + "fcvtnu_asisdmisc_r"_h, + "fcvtps_asisdmisc_r"_h, + "fcvtpu_asisdmisc_r"_h, + "fcvtzs_asisdmisc_r"_h, + "fcvtzu_asisdmisc_r"_h, + "frecpe_asisdmisc_r"_h, + "frecpx_asisdmisc_r"_h, + "frsqrte_asisdmisc_r"_h, + "scvtf_asisdmisc_r"_h, + "ucvtf_asisdmisc_r"_h}}, + {"'?22:ds'u0400, '?22:ds'u0905, #0.0", + {"fcmeq_asisdmisc_fz"_h, + "fcmge_asisdmisc_fz"_h, + "fcmgt_asisdmisc_fz"_h, + "fcmle_asisdmisc_fz"_h, + "fcmlt_asisdmisc_fz"_h}}, + {"'?22:ds'u0400, '?22:ds'u0905, '?22:ds'u2016", + {"fabd_asisdsame_only"_h, + "facge_asisdsame_only"_h, + "facgt_asisdsame_only"_h, + "fcmeq_asisdsame_only"_h, + "fcmge_asisdsame_only"_h, + "fcmgt_asisdsame_only"_h, + "fmulx_asisdsame_only"_h, + "frecps_asisdsame_only"_h, + "frsqrts_asisdsame_only"_h}}, + {"'?22:ds'u0400, '?22:ds'u0905, 'Vf.'?22:ds[']", + {"fmla_asisdelem_r_sd"_h, + "fmls_asisdelem_r_sd"_h, + "fmul_asisdelem_r_sd"_h, + "fmulx_asisdelem_r_sd"_h}}, + {"'?22:ds'u0400, 'Vn.2'?22:ds", + {"faddp_asisdpair_only_sd"_h, + "fmaxnmp_asisdpair_only_sd"_h, + "fmaxp_asisdpair_only_sd"_h, + "fminnmp_asisdpair_only_sd"_h, + "fminp_asisdpair_only_sd"_h}}, + {"'Bt, ['Xns'(2012?, #'s2012)]", + {"ldur_b_ldst_unscaled"_h, "stur_b_ldst_unscaled"_h}}, + {"'Bt, ['Xns'(2110?, #'u2110)]", + {"ldr_b_ldst_pos"_h, "str_b_ldst_pos"_h}}, + {"'Bt, ['Xns, #'s2012]!", {"ldr_b_ldst_immpre"_h, "str_b_ldst_immpre"_h}}, + {"'Bt, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #0)]", + {"ldr_b_ldst_regoff"_h, + "ldr_bl_ldst_regoff"_h, + "str_b_ldst_regoff"_h, + "str_bl_ldst_regoff"_h}}, + {"'Bt, ['Xns], #'s2012", + {"ldr_b_ldst_immpost"_h, "str_b_ldst_immpost"_h}}, + {"'Dd, 'Dn", {"abs_asisdmisc_r"_h, "neg_asisdmisc_r"_h}}, + {"'Dd, 'Dn, #0", + {"cmeq_asisdmisc_z"_h, + "cmge_asisdmisc_z"_h, + "cmgt_asisdmisc_z"_h, + "cmle_asisdmisc_z"_h, + "cmlt_asisdmisc_z"_h}}, + {"'Dd, 'Dn, 'Dm", + {"cmeq_asisdsame_only"_h, + "cmge_asisdsame_only"_h, + "cmgt_asisdsame_only"_h, + "cmhi_asisdsame_only"_h, + "cmhs_asisdsame_only"_h, + "cmtst_asisdsame_only"_h, + "add_asisdsame_only"_h, + "sub_asisdsame_only"_h}}, + {"'Dd, 'Dn, #'<16 31 u2219 clz32 - lsl u2216 ->", + {"sri_asisdshf_r"_h, + "srshr_asisdshf_r"_h, + "srsra_asisdshf_r"_h, + "sshr_asisdshf_r"_h, + "ssra_asisdshf_r"_h, + "urshr_asisdshf_r"_h, + "ursra_asisdshf_r"_h, + "ushr_asisdshf_r"_h, + "usra_asisdshf_r"_h}}, + {"'Dd, 'Dn, #'", + {"shl_asisdshf_r"_h, "sli_asisdshf_r"_h}}, + {"'Dd, 'Hn", {"fcvt_dh_floatdp1"_h}}, + {"'Dd, #'f2013", {"fmov_d_floatimm"_h}}, + {"'Dd, #0x'<0xff 56 lsl u18 * 0xff 48 lsl u17 * + 0xff 40 lsl u16 * + " + "0xff 32 lsl u09 * + 0xff 24 lsl u08 * + 0xff0000 u07 * + 0xff00 u06 * " + "+ 0xff u05 * + hex>", + {"movi_asimdimm_d_ds"_h}}, + {"'Dd, 'Pgl, 'Zn.'[sz]", {"saddv_r_p_z"_h, "uaddv_r_p_z"_h}}, + {"'Dd, 'Sn", {"fcvt_ds_floatdp1"_h}}, + {"'Dd, 'Vn.2d", {"addp_asisdpair_only"_h}}, + {"'Dt, 'Dt2, ['Xns'(2115?, #')]", + {"ldnp_d_ldstnapair_offs"_h, + "ldp_d_ldstpair_off"_h, + "stnp_d_ldstnapair_offs"_h, + "stp_d_ldstpair_off"_h}}, + {"'Dt, 'Dt2, ['Xns, #']!", + {"ldp_d_ldstpair_pre"_h, "stp_d_ldstpair_pre"_h}}, + {"'Dt, 'Dt2, ['Xns], #'", + {"ldp_d_ldstpair_post"_h, "stp_d_ldstpair_post"_h}}, + {"'Dt, pc'(23?:+)' 'LValue", {"ldr_d_loadlit"_h}}, + {"'Dt, ['Xns'(2012?, #'s2012)]", + {"ldur_d_ldst_unscaled"_h, "stur_d_ldst_unscaled"_h}}, + {"'Dt, ['Xns'(2110?, #')]", + {"ldr_d_ldst_pos"_h, "str_d_ldst_pos"_h}}, + {"'Dt, ['Xns, #'s2012]!", {"ldr_d_ldst_immpre"_h, "str_d_ldst_immpre"_h}}, + {"'Dt, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #3)]", + {"ldr_d_ldst_regoff"_h, "str_d_ldst_regoff"_h}}, + {"'Dt, ['Xns], #'s2012", + {"ldr_d_ldst_immpost"_h, "str_d_ldst_immpost"_h}}, + {"'Fd, 'Fn", {"fabs_d_floatdp1"_h, "fabs_h_floatdp1"_h, + "fabs_s_floatdp1"_h, "fmov_d_floatdp1"_h, + "fmov_h_floatdp1"_h, "fmov_s_floatdp1"_h, + "fneg_d_floatdp1"_h, "fneg_h_floatdp1"_h, + "fneg_s_floatdp1"_h, "frint32x_d_floatdp1"_h, + "frint32x_s_floatdp1"_h, "frint32z_d_floatdp1"_h, + "frint32z_s_floatdp1"_h, "frint64x_d_floatdp1"_h, + "frint64x_s_floatdp1"_h, "frint64z_d_floatdp1"_h, + "frint64z_s_floatdp1"_h, "frinta_d_floatdp1"_h, + "frinta_h_floatdp1"_h, "frinta_s_floatdp1"_h, + "frinti_d_floatdp1"_h, "frinti_h_floatdp1"_h, + "frinti_s_floatdp1"_h, "frintm_d_floatdp1"_h, + "frintm_h_floatdp1"_h, "frintm_s_floatdp1"_h, + "frintn_d_floatdp1"_h, "frintn_h_floatdp1"_h, + "frintn_s_floatdp1"_h, "frintp_d_floatdp1"_h, + "frintp_h_floatdp1"_h, "frintp_s_floatdp1"_h, + "frintx_d_floatdp1"_h, "frintx_h_floatdp1"_h, + "frintx_s_floatdp1"_h, "frintz_d_floatdp1"_h, + "frintz_h_floatdp1"_h, "frintz_s_floatdp1"_h, + "fsqrt_d_floatdp1"_h, "fsqrt_h_floatdp1"_h, + "fsqrt_s_floatdp1"_h}}, + {"'Fd, 'Fn, 'Fm", + {"fadd_d_floatdp2"_h, "fadd_h_floatdp2"_h, "fadd_s_floatdp2"_h, + "fdiv_d_floatdp2"_h, "fdiv_h_floatdp2"_h, "fdiv_s_floatdp2"_h, + "fmax_d_floatdp2"_h, "fmax_h_floatdp2"_h, "fmax_s_floatdp2"_h, + "fmaxnm_d_floatdp2"_h, "fmaxnm_h_floatdp2"_h, "fmaxnm_s_floatdp2"_h, + "fmin_d_floatdp2"_h, "fmin_h_floatdp2"_h, "fmin_s_floatdp2"_h, + "fminnm_d_floatdp2"_h, "fminnm_h_floatdp2"_h, "fminnm_s_floatdp2"_h, + "fmul_d_floatdp2"_h, "fmul_h_floatdp2"_h, "fmul_s_floatdp2"_h, + "fnmul_d_floatdp2"_h, "fnmul_h_floatdp2"_h, "fnmul_s_floatdp2"_h, + "fsub_d_floatdp2"_h, "fsub_h_floatdp2"_h, "fsub_s_floatdp2"_h}}, + {"'Fd, 'Fn, 'Fm, '[cond]", + {"fcsel_d_floatsel"_h, "fcsel_h_floatsel"_h, "fcsel_s_floatsel"_h}}, + {"'Fd, 'Fn, 'Fm, 'Fa", + {"fmadd_d_floatdp3"_h, + "fmadd_h_floatdp3"_h, + "fmadd_s_floatdp3"_h, + "fmsub_d_floatdp3"_h, + "fmsub_h_floatdp3"_h, + "fmsub_s_floatdp3"_h, + "fnmadd_d_floatdp3"_h, + "fnmadd_h_floatdp3"_h, + "fnmadd_s_floatdp3"_h, + "fnmsub_d_floatdp3"_h, + "fnmsub_h_floatdp3"_h, + "fnmsub_s_floatdp3"_h}}, + {"'Fd, 'Rn", + {"fmov_d64_float2int"_h, + "fmov_h32_float2int"_h, + "fmov_h64_float2int"_h, + "fmov_s32_float2int"_h, + "scvtf_d32_float2int"_h, + "scvtf_d64_float2int"_h, + "scvtf_h32_float2int"_h, + "scvtf_h64_float2int"_h, + "scvtf_s32_float2int"_h, + "scvtf_s64_float2int"_h, + "ucvtf_d32_float2int"_h, + "ucvtf_d64_float2int"_h, + "ucvtf_h32_float2int"_h, + "ucvtf_h64_float2int"_h, + "ucvtf_s32_float2int"_h, + "ucvtf_s64_float2int"_h}}, + {"'Fd, 'Rn, #'<64 u1510 ->", + {"scvtf_d32_float2fix"_h, + "scvtf_d64_float2fix"_h, + "scvtf_h32_float2fix"_h, + "scvtf_h64_float2fix"_h, + "scvtf_s32_float2fix"_h, + "scvtf_s64_float2fix"_h, + "ucvtf_d32_float2fix"_h, + "ucvtf_d64_float2fix"_h, + "ucvtf_h32_float2fix"_h, + "ucvtf_h64_float2fix"_h, + "ucvtf_s32_float2fix"_h, + "ucvtf_s64_float2fix"_h}}, + {"'Fn, #0.0", + {"fcmp_dz_floatcmp"_h, + "fcmp_hz_floatcmp"_h, + "fcmp_sz_floatcmp"_h, + "fcmpe_dz_floatcmp"_h, + "fcmpe_hz_floatcmp"_h, + "fcmpe_sz_floatcmp"_h}}, + {"'Fn, 'Fm", + {"fcmp_d_floatcmp"_h, + "fcmp_h_floatcmp"_h, + "fcmp_s_floatcmp"_h, + "fcmpe_d_floatcmp"_h, + "fcmpe_h_floatcmp"_h, + "fcmpe_s_floatcmp"_h}}, + {"'Fn, 'Fm, #'[nzcv], '[cond]", + {"fccmp_d_floatccmp"_h, + "fccmp_h_floatccmp"_h, + "fccmp_s_floatccmp"_h, + "fccmpe_d_floatccmp"_h, + "fccmpe_h_floatccmp"_h, + "fccmpe_s_floatccmp"_h}}, + {"'Hd, 'Dn", {"fcvt_hd_floatdp1"_h}}, + {"'Hd, 'Hn", + {"fcvtas_asisdmiscfp16_r"_h, + "fcvtau_asisdmiscfp16_r"_h, + "fcvtms_asisdmiscfp16_r"_h, + "fcvtmu_asisdmiscfp16_r"_h, + "fcvtns_asisdmiscfp16_r"_h, + "fcvtnu_asisdmiscfp16_r"_h, + "fcvtps_asisdmiscfp16_r"_h, + "fcvtpu_asisdmiscfp16_r"_h, + "fcvtzs_asisdmiscfp16_r"_h, + "fcvtzu_asisdmiscfp16_r"_h, + "frecpe_asisdmiscfp16_r"_h, + "frecpx_asisdmiscfp16_r"_h, + "frsqrte_asisdmiscfp16_r"_h, + "scvtf_asisdmiscfp16_r"_h, + "ucvtf_asisdmiscfp16_r"_h}}, + {"'Hd, 'Hn, #0.0", + {"fcmeq_asisdmiscfp16_fz"_h, + "fcmge_asisdmiscfp16_fz"_h, + "fcmgt_asisdmiscfp16_fz"_h, + "fcmle_asisdmiscfp16_fz"_h, + "fcmlt_asisdmiscfp16_fz"_h}}, + {"'Hd, 'Hn, 'Hm", + {"fabd_asisdsamefp16_only"_h, + "facge_asisdsamefp16_only"_h, + "facgt_asisdsamefp16_only"_h, + "fcmeq_asisdsamefp16_only"_h, + "fcmge_asisdsamefp16_only"_h, + "fcmgt_asisdsamefp16_only"_h, + "fmulx_asisdsamefp16_only"_h, + "frecps_asisdsamefp16_only"_h, + "frsqrts_asisdsamefp16_only"_h}}, + {"'Hd, 'Hn, 'Vf.h[']", + {"fmla_asisdelem_rh_h"_h, + "fmls_asisdelem_rh_h"_h, + "fmul_asisdelem_rh_h"_h, + "fmulx_asisdelem_rh_h"_h}}, + {"'Hd, #'f2013", {"fmov_h_floatimm"_h}}, + {"'Hd, 'Sn", {"bfcvt_bs_floatdp1"_h, "fcvt_hs_floatdp1"_h}}, + {"'Hd, 'Vn.'?30:84h", + {"fmaxnmv_asimdall_only_h"_h, + "fmaxv_asimdall_only_h"_h, + "fminnmv_asimdall_only_h"_h, + "fminv_asimdall_only_h"_h}}, + {"'Hd, 'Vn.2h", + {"faddp_asisdpair_only_h"_h, + "fmaxnmp_asisdpair_only_h"_h, + "fmaxp_asisdpair_only_h"_h, + "fminnmp_asisdpair_only_h"_h, + "fminp_asisdpair_only_h"_h}}, + {"'Ht, ['Xns'(2012?, #'s2012)]", + {"ldur_h_ldst_unscaled"_h, "stur_h_ldst_unscaled"_h}}, + {"'Ht, ['Xns'(2110?, #')]", + {"ldr_h_ldst_pos"_h, "str_h_ldst_pos"_h}}, + {"'Ht, ['Xns, #'s2012]!", {"ldr_h_ldst_immpre"_h, "str_h_ldst_immpre"_h}}, + {"'Ht, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #1)]", + {"ldr_h_ldst_regoff"_h, "str_h_ldst_regoff"_h}}, + {"'Ht, ['Xns], #'s2012", + {"ldr_h_ldst_immpost"_h, "str_h_ldst_immpost"_h}}, + {"'IY, 'Xt", {"msr_sr_systemmove"_h}}, + {"'[barrier]", {"dsb_bo_barriers"_h}}, + {"'Pd, ['Xns'(2110?, #'s2116_1210, mul vl)]", + {"ldr_p_bi"_h, "str_p_bi"_h}}, + {"'Pd.'[sz]'(0905=31?:, '[mulpat])", {"ptrue_p_s"_h, "ptrues_p_s"_h}}, + {"'Pd.'[sz], 'Pgl/z, 'Zn.'[sz], #'s2016", + {"cmpeq_p_p_zi"_h, + "cmpge_p_p_zi"_h, + "cmpgt_p_p_zi"_h, + "cmple_p_p_zi"_h, + "cmplt_p_p_zi"_h, + "cmpne_p_p_zi"_h}}, + {"'Pd.'[sz], 'Pgl/z, 'Zn.'[sz], #'u2014", + {"cmphi_p_p_zi"_h, + "cmphs_p_p_zi"_h, + "cmplo_p_p_zi"_h, + "cmpls_p_p_zi"_h}}, + {"'Pd.'[sz], 'Pgl/z, 'Zn.'[sz], #0.0", + {"fcmeq_p_p_z0"_h, + "fcmge_p_p_z0"_h, + "fcmgt_p_p_z0"_h, + "fcmle_p_p_z0"_h, + "fcmlt_p_p_z0"_h, + "fcmne_p_p_z0"_h}}, + {"'Pd.'[sz], 'Pgl/z, 'Zn.'[sz], 'Zm.'[sz]", + {"cmpeq_p_p_zz"_h, + "cmpge_p_p_zz"_h, + "cmpgt_p_p_zz"_h, + "cmphi_p_p_zz"_h, + "cmphs_p_p_zz"_h, + "cmpne_p_p_zz"_h, + "facge_p_p_zz"_h, + "facgt_p_p_zz"_h, + "fcmeq_p_p_zz"_h, + "fcmge_p_p_zz"_h, + "fcmgt_p_p_zz"_h, + "fcmne_p_p_zz"_h, + "fcmuo_p_p_zz"_h, + "match_p_p_zz"_h, + "nmatch_p_p_zz"_h}}, + {"'Pd.'[sz], 'Pgl/z, 'Zn.'[sz], 'Zm.d", + {"cmpeq_p_p_zw"_h, + "cmpge_p_p_zw"_h, + "cmpgt_p_p_zw"_h, + "cmphi_p_p_zw"_h, + "cmphs_p_p_zw"_h, + "cmple_p_p_zw"_h, + "cmplo_p_p_zw"_h, + "cmpls_p_p_zw"_h, + "cmplt_p_p_zw"_h, + "cmpne_p_p_zw"_h}}, + {"'Pd.'[sz], 'Pn, 'Pd.'[sz]", {"pnext_p_p_p"_h}}, + {"'Pd.'[sz], 'Pn.'[sz]", {"rev_p_p"_h}}, + {"'Pd.'[sz], 'Pn.'[sz], 'Pm.'[sz]", + {"trn1_p_pp"_h, + "trn2_p_pp"_h, + "uzp1_p_pp"_h, + "uzp2_p_pp"_h, + "zip1_p_pp"_h, + "zip2_p_pp"_h}}, + {"'Pd.'[sz], 'R12n, 'R12m", + {"whilege_p_p_rr"_h, + "whilegt_p_p_rr"_h, + "whilehi_p_p_rr"_h, + "whilehs_p_p_rr"_h, + "whilele_p_p_rr"_h, + "whilelo_p_p_rr"_h, + "whilels_p_p_rr"_h, + "whilelt_p_p_rr"_h, + "whilerw_p_rr"_h, + "whilewr_p_rr"_h}}, + {"'Pd.b", {"pfalse_p"_h, "rdffr_p_f"_h}}, + {"'Pd.b, 'Pn.b", {"movs_orrs_p_p_pp_z"_h, "mov_orr_p_p_pp_z"_h}}, + {"'Pd.b, 'Pn, 'Pd.b", {"pfirst_p_p_p"_h}}, + {"'Pd.b, 'Pn/z", {"rdffrs_p_p_f"_h, "rdffr_p_p_f"_h}}, + {"'Pd.b, 'Pm/z, 'Pn.b", {"nots_eors_p_p_pp_z"_h, "not_eor_p_p_pp_z"_h}}, + {"'Pd.b, p'u1310, 'Pn.b, 'Pm.b", {"sel_p_p_pp"_h}}, + {"'Pd.b, p'u1310/'?04:mz, 'Pn.b", + {"brka_p_p_p"_h, + "brkas_p_p_p_z"_h, + "brkb_p_p_p"_h, + "brkbs_p_p_p_z"_h, + "movs_ands_p_p_pp_z"_h, + "mov_and_p_p_pp_z"_h, + "mov_sel_p_p_pp"_h}}, + {"'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b", {"brkn_p_p_pp"_h, "brkns_p_p_pp"_h}}, + {"'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b", + {"brkpas_p_p_pp"_h, + "brkpa_p_p_pp"_h, + "brkpbs_p_p_pp"_h, + "brkpb_p_p_pp"_h, + "ands_p_p_pp_z"_h, + "and_p_p_pp_z"_h, + "bics_p_p_pp_z"_h, + "bic_p_p_pp_z"_h, + "eors_p_p_pp_z"_h, + "eor_p_p_pp_z"_h, + "nands_p_p_pp_z"_h, + "nand_p_p_pp_z"_h, + "nors_p_p_pp_z"_h, + "nor_p_p_pp_z"_h, + "orns_p_p_pp_z"_h, + "orn_p_p_pp_z"_h, + "orrs_p_p_pp_z"_h, + "orr_p_p_pp_z"_h}}, + {"'Pd.h, 'Pn.b", {"punpkhi_p_p"_h, "punpklo_p_p"_h}}, + {"'Pn.b", {"wrffr_f_p"_h}}, + {"'Qd, 'Qn, 'Vm.2d", + {"sha512h2_qqv_cryptosha512_3"_h, "sha512h_qqv_cryptosha512_3"_h}}, + {"'Qd, 'Qn, 'Vm.4s", + {"sha256h2_qqv_cryptosha3"_h, "sha256h_qqv_cryptosha3"_h}}, + {"'Qd, 'Sn, 'Vm.4s", + {"sha1c_qsv_cryptosha3"_h, + "sha1m_qsv_cryptosha3"_h, + "sha1p_qsv_cryptosha3"_h}}, + {"'Qt, pc'(23?:+)' 'LValue", {"ldr_q_loadlit"_h}}, + {"'Qt, 'Qt2, ['Xns'(2115?, #')]", + {"ldnp_q_ldstnapair_offs"_h, + "ldp_q_ldstpair_off"_h, + "stnp_q_ldstnapair_offs"_h, + "stp_q_ldstpair_off"_h}}, + {"'Qt, 'Qt2, ['Xns, #']!", + {"ldp_q_ldstpair_pre"_h, "stp_q_ldstpair_pre"_h}}, + {"'Qt, 'Qt2, ['Xns], #'", + {"ldp_q_ldstpair_post"_h, "stp_q_ldstpair_post"_h}}, + {"'Qt, ['Xns'(2012?, #'s2012)]", + {"ldur_q_ldst_unscaled"_h, "stur_q_ldst_unscaled"_h}}, + {"'Qt, ['Xns'(2110?, #')]", + {"ldr_q_ldst_pos"_h, "str_q_ldst_pos"_h}}, + {"'Qt, ['Xns, #'s2012]!", {"ldr_q_ldst_immpre"_h, "str_q_ldst_immpre"_h}}, + {"'Qt, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #4)]", + {"ldr_q_ldst_regoff"_h, "str_q_ldst_regoff"_h}}, + {"'Qt, ['Xns], #'s2012", + {"ldr_q_ldst_immpost"_h, "str_q_ldst_immpost"_h}}, + {"'R20d'(1916?, '[mulpat], mul #''$)'(0905=31?:, '[mulpat])", + {"sqdecb_r_rs_x"_h, "sqdecd_r_rs_x"_h, "sqdech_r_rs_x"_h, + "sqdecw_r_rs_x"_h, "sqincb_r_rs_x"_h, "sqincd_r_rs_x"_h, + "sqinch_r_rs_x"_h, "sqincw_r_rs_x"_h, "uqdecb_r_rs_uw"_h, + "uqdecb_r_rs_x"_h, "uqdecd_r_rs_uw"_h, "uqdecd_r_rs_x"_h, + "uqdech_r_rs_uw"_h, "uqdech_r_rs_x"_h, "uqdecw_r_rs_uw"_h, + "uqdecw_r_rs_x"_h, "uqincb_r_rs_uw"_h, "uqincb_r_rs_x"_h, + "uqincd_r_rs_uw"_h, "uqincd_r_rs_x"_h, "uqinch_r_rs_uw"_h, + "uqinch_r_rs_x"_h, "uqincw_r_rs_uw"_h, "uqincw_r_rs_x"_h}}, + {"'R22n, 'R22m", {"ctermeq_rr"_h, "ctermne_rr"_h}}, + {"'Rd, #0x'x2005'(2221?, lsl #')", + {"movk_32_movewide"_h, "movk_64_movewide"_h}}, + {"'Rd, '[condinv]", + {"cset_csinc_32_condsel"_h, + "cset_csinc_64_condsel"_h, + "csetm_csinv_32_condsel"_h, + "csetm_csinv_64_condsel"_h}}, + {"'Rd, 'Fn", {"fcvtas_32d_float2int"_h, "fcvtas_32h_float2int"_h, + "fcvtas_32s_float2int"_h, "fcvtas_64d_float2int"_h, + "fcvtas_64h_float2int"_h, "fcvtas_64s_float2int"_h, + "fcvtau_32d_float2int"_h, "fcvtau_32h_float2int"_h, + "fcvtau_32s_float2int"_h, "fcvtau_64d_float2int"_h, + "fcvtau_64h_float2int"_h, "fcvtau_64s_float2int"_h, + "fcvtms_32d_float2int"_h, "fcvtms_32h_float2int"_h, + "fcvtms_32s_float2int"_h, "fcvtms_64d_float2int"_h, + "fcvtms_64h_float2int"_h, "fcvtms_64s_float2int"_h, + "fcvtmu_32d_float2int"_h, "fcvtmu_32h_float2int"_h, + "fcvtmu_32s_float2int"_h, "fcvtmu_64d_float2int"_h, + "fcvtmu_64h_float2int"_h, "fcvtmu_64s_float2int"_h, + "fcvtns_32d_float2int"_h, "fcvtns_32h_float2int"_h, + "fcvtns_32s_float2int"_h, "fcvtns_64d_float2int"_h, + "fcvtns_64h_float2int"_h, "fcvtns_64s_float2int"_h, + "fcvtnu_32d_float2int"_h, "fcvtnu_32h_float2int"_h, + "fcvtnu_32s_float2int"_h, "fcvtnu_64d_float2int"_h, + "fcvtnu_64h_float2int"_h, "fcvtnu_64s_float2int"_h, + "fcvtps_32d_float2int"_h, "fcvtps_32h_float2int"_h, + "fcvtps_32s_float2int"_h, "fcvtps_64d_float2int"_h, + "fcvtps_64h_float2int"_h, "fcvtps_64s_float2int"_h, + "fcvtpu_32d_float2int"_h, "fcvtpu_32h_float2int"_h, + "fcvtpu_32s_float2int"_h, "fcvtpu_64d_float2int"_h, + "fcvtpu_64h_float2int"_h, "fcvtpu_64s_float2int"_h, + "fcvtzs_32d_float2int"_h, "fcvtzs_32h_float2int"_h, + "fcvtzs_32s_float2int"_h, "fcvtzs_64d_float2int"_h, + "fcvtzs_64h_float2int"_h, "fcvtzs_64s_float2int"_h, + "fcvtzu_32d_float2int"_h, "fcvtzu_32h_float2int"_h, + "fcvtzu_32s_float2int"_h, "fcvtzu_64d_float2int"_h, + "fcvtzu_64h_float2int"_h, "fcvtzu_64s_float2int"_h, + "fjcvtzs_32d_float2int"_h, "fmov_32h_float2int"_h, + "fmov_32s_float2int"_h, "fmov_64d_float2int"_h, + "fmov_64h_float2int"_h}}, + {"'Rd, 'Fn, #'<64 u1510 ->", + {"fcvtzs_32d_float2fix"_h, + "fcvtzs_32h_float2fix"_h, + "fcvtzs_32s_float2fix"_h, + "fcvtzs_64d_float2fix"_h, + "fcvtzs_64h_float2fix"_h, + "fcvtzs_64s_float2fix"_h, + "fcvtzu_32d_float2fix"_h, + "fcvtzu_32h_float2fix"_h, + "fcvtzu_32s_float2fix"_h, + "fcvtzu_64d_float2fix"_h, + "fcvtzu_64h_float2fix"_h, + "fcvtzu_64s_float2fix"_h}}, + {"'Rd, #'<32 u2116 ->, #'", {"bfc_bfm_32m_bitfield"_h}}, + {"'Rd, #'<64 u2116 ->, #'", {"bfc_bfm_64m_bitfield"_h}}, + {"'Rd, #0x'", + {"movz_32_movewide"_h, + "movz_64_movewide"_h, + "movn_32_movewide"_h, + "movn_64_movewide"_h, + "mov_movz_32_movewide"_h, + "mov_movz_64_movewide"_h}}, + {"'Rd, #0x'", + {"mov_movn_32_movewide"_h}}, + {"'Rd, #0x'", {"mov_movn_64_movewide"_h}}, + {"'Rd, 'Rm", + {"ngc_sbc_32_addsub_carry"_h, + "ngc_sbc_64_addsub_carry"_h, + "ngcs_sbcs_32_addsub_carry"_h, + "ngcs_sbcs_64_addsub_carry"_h, + "mov_orr_32_log_shift"_h, + "mov_orr_64_log_shift"_h}}, + {"'Rd, 'Rm'(1510?, '[shift] #'u1510)", + {"neg_sub_32_addsub_shift"_h, + "neg_sub_64_addsub_shift"_h, + "negs_subs_32_addsub_shift"_h, + "negs_subs_64_addsub_shift"_h, + "mvn_orn_32_log_shift"_h, + "mvn_orn_64_log_shift"_h}}, + {"'Rd, 'Rn", + {"abs_32_dp_1src"_h, + "abs_64_dp_1src"_h, + "cls_32_dp_1src"_h, + "cls_64_dp_1src"_h, + "clz_32_dp_1src"_h, + "clz_64_dp_1src"_h, + "cnt_32_dp_1src"_h, + "cnt_64_dp_1src"_h, + "ctz_32_dp_1src"_h, + "ctz_64_dp_1src"_h, + "rbit_32_dp_1src"_h, + "rbit_64_dp_1src"_h, + "rev16_32_dp_1src"_h, + "rev16_64_dp_1src"_h, + "rev32_64_dp_1src"_h, + "rev_32_dp_1src"_h, + "rev_64_dp_1src"_h}}, + {"'Rd, 'Rn, #'s1710", + {"smax_32_minmax_imm"_h, + "smax_64_minmax_imm"_h, + "smin_32_minmax_imm"_h, + "smin_64_minmax_imm"_h}}, + {"'Rd, 'Rn, #'u1510", {"ror_extr_32_extract"_h, "ror_extr_64_extract"_h}}, + {"'Rd, 'Rn, #'u1710", + {"umax_32u_minmax_imm"_h, + "umax_64u_minmax_imm"_h, + "umin_32u_minmax_imm"_h, + "umin_64u_minmax_imm"_h}}, + {"'Rd, 'Rn, '[condinv]", + {"cinc_csinc_32_condsel"_h, + "cinc_csinc_64_condsel"_h, + "cinv_csinv_32_condsel"_h, + "cinv_csinv_64_condsel"_h, + "cneg_csneg_32_condsel"_h, + "cneg_csneg_64_condsel"_h}}, + {"'Rd, 'Rn, #'u2116", + {"asr_sbfm_32m_bitfield"_h, + "asr_sbfm_64m_bitfield"_h, + "lsr_ubfm_32m_bitfield"_h, + "lsr_ubfm_64m_bitfield"_h}}, + {"'Rd, 'Rn, #'u2116, #'<1 u1510 u2116 - +>", + {"sbfx_sbfm_32m_bitfield"_h, + "sbfx_sbfm_64m_bitfield"_h, + "ubfx_ubfm_32m_bitfield"_h, + "ubfx_ubfm_64m_bitfield"_h, + "bfxil_bfm_32m_bitfield"_h, + "bfxil_bfm_64m_bitfield"_h}}, + {"'Rd, 'Rn, #'<32 u2116 ->", {"lsl_ubfm_32m_bitfield"_h}}, + {"'Rd, 'Rn, #'<64 u2116 ->", {"lsl_ubfm_64m_bitfield"_h}}, + {"'Rd, 'Rn, #'<32 u2116 ->, #'", + {"sbfiz_sbfm_32m_bitfield"_h, + "ubfiz_ubfm_32m_bitfield"_h, + "bfi_bfm_32m_bitfield"_h}}, + {"'Rd, 'Rn, #'<64 u2116 ->, #'", + {"sbfiz_sbfm_64m_bitfield"_h, + "ubfiz_ubfm_64m_bitfield"_h, + "bfi_bfm_64m_bitfield"_h}}, + {"'Rd, 'Rn, 'Rm", {"crc32b_32c_dp_2src"_h, "crc32cb_32c_dp_2src"_h, + "crc32ch_32c_dp_2src"_h, "crc32cw_32c_dp_2src"_h, + "crc32h_32c_dp_2src"_h, "crc32w_32c_dp_2src"_h, + "sdiv_32_dp_2src"_h, "sdiv_64_dp_2src"_h, + "smax_32_dp_2src"_h, "smax_64_dp_2src"_h, + "smin_32_dp_2src"_h, "smin_64_dp_2src"_h, + "udiv_32_dp_2src"_h, "udiv_64_dp_2src"_h, + "umax_32_dp_2src"_h, "umax_64_dp_2src"_h, + "umin_32_dp_2src"_h, "umin_64_dp_2src"_h, + "adcs_32_addsub_carry"_h, "adcs_64_addsub_carry"_h, + "adc_32_addsub_carry"_h, "adc_64_addsub_carry"_h, + "sbcs_32_addsub_carry"_h, "sbcs_64_addsub_carry"_h, + "sbc_32_addsub_carry"_h, "sbc_64_addsub_carry"_h, + "mul_madd_32a_dp_3src"_h, "mul_madd_64a_dp_3src"_h, + "mneg_msub_32a_dp_3src"_h, "mneg_msub_64a_dp_3src"_h, + "asr_asrv_32_dp_2src"_h, "asr_asrv_64_dp_2src"_h, + "lsl_lslv_32_dp_2src"_h, "lsl_lslv_64_dp_2src"_h, + "lsr_lsrv_32_dp_2src"_h, "lsr_lsrv_64_dp_2src"_h, + "ror_rorv_32_dp_2src"_h, "ror_rorv_64_dp_2src"_h}}, + {"'Rd, 'Rn, 'Rm, #'u1510", {"extr_32_extract"_h, "extr_64_extract"_h}}, + {"'Rd, 'Rn, 'Rm, '[cond]", + {"csel_32_condsel"_h, + "csel_64_condsel"_h, + "csinc_32_condsel"_h, + "csinc_64_condsel"_h, + "csinv_32_condsel"_h, + "csinv_64_condsel"_h, + "csneg_32_condsel"_h, + "csneg_64_condsel"_h}}, + {"'Rd, 'Rn, 'Rm, 'Ra", + {"madd_32a_dp_3src"_h, + "madd_64a_dp_3src"_h, + "msub_32a_dp_3src"_h, + "msub_64a_dp_3src"_h}}, + {"'Rd, 'Rn, 'Rm'(1510?, '[shift] #'u1510)", + {"adds_32_addsub_shift"_h, "adds_64_addsub_shift"_h, + "add_32_addsub_shift"_h, "add_64_addsub_shift"_h, + "subs_32_addsub_shift"_h, "subs_64_addsub_shift"_h, + "sub_32_addsub_shift"_h, "sub_64_addsub_shift"_h, + "ands_32_log_shift"_h, "ands_64_log_shift"_h, + "and_32_log_shift"_h, "and_64_log_shift"_h, + "bics_32_log_shift"_h, "bics_64_log_shift"_h, + "bic_32_log_shift"_h, "bic_64_log_shift"_h, + "eon_32_log_shift"_h, "eon_64_log_shift"_h, + "eor_32_log_shift"_h, "eor_64_log_shift"_h, + "orn_32_log_shift"_h, "orn_64_log_shift"_h, + "orr_32_log_shift"_h, "orr_64_log_shift"_h}}, + {"'Rd, 'Vn.D[1]", {"fmov_64vx_float2int"_h}}, + {"'Rd, 'Wn", + {"sxtb_sbfm_32m_bitfield"_h, + "sxtb_sbfm_64m_bitfield"_h, + "sxth_sbfm_32m_bitfield"_h, + "sxth_sbfm_64m_bitfield"_h, + "sxtw_sbfm_64m_bitfield"_h, + "uxtb_ubfm_32m_bitfield"_h, + "uxtb_ubfm_64m_bitfield"_h, + "uxth_ubfm_32m_bitfield"_h, + "uxth_ubfm_64m_bitfield"_h}}, + {"'Rd, 'Xns, 'Rm", {"gmi_64g_dp_2src"_h}}, + {"'Rds, 'ITri", {"mov_orr_32_log_imm"_h, "mov_orr_64_log_imm"_h}}, + {"'Rds, 'Rn, 'ITri", + {"ands_32s_log_imm"_h, + "ands_64s_log_imm"_h, + "and_32_log_imm"_h, + "and_64_log_imm"_h, + "eor_32_log_imm"_h, + "eor_64_log_imm"_h, + "orr_32_log_imm"_h, + "orr_64_log_imm"_h}}, + {"'Rds, 'Rns", {"mov_add_32_addsub_imm"_h, "mov_add_64_addsub_imm"_h}}, + {"'Rds, 'Rns, '(1413=3?x:w)'(2016=31?zr:'u2016), '[ext]'(1210? #'u1210)", + {"adds_32s_addsub_ext"_h, + "add_32_addsub_ext"_h, + "subs_32s_addsub_ext"_h, + "sub_32_addsub_ext"_h, + "adds_32s_addsub_ext"_h, + "adds_64s_addsub_ext"_h, + "add_64_addsub_ext"_h, + "subs_64s_addsub_ext"_h, + "sub_64_addsub_ext"_h}}, + {"'Rds, 'Rns, " + "'(1413=3?x:w)'(2016=31?zr:'u2016)'(1510=16?:, '[ext32])'(1210? " + "#'u1210)", + {"adds_lsl_adds_32s_addsub_ext"_h, + "add_lsl_add_32_addsub_ext"_h, + "subs_lsl_subs_32s_addsub_ext"_h, + "sub_lsl_sub_32_addsub_ext"_h}}, + {"'Rds, 'Rns, " + "'(1413=3?x:w)'(2016=31?zr:'u2016)'(1510=24?:, '[ext64])'(1210? " + "#'u1210)", + {"adds_lsl_adds_64s_addsub_ext"_h, + "add_lsl_add_64_addsub_ext"_h, + "subs_lsl_subs_64s_addsub_ext"_h, + "sub_lsl_sub_64_addsub_ext"_h}}, + {"'Rds, 'Rns, #0x'(22?':'x2110) ('(22?':'u2110))", + {"adds_32s_addsub_imm"_h, + "adds_64s_addsub_imm"_h, + "add_32_addsub_imm"_h, + "add_64_addsub_imm"_h, + "subs_32s_addsub_imm"_h, + "subs_64s_addsub_imm"_h, + "sub_32_addsub_imm"_h, + "sub_64_addsub_imm"_h}}, + {"'Rn, #'u2016, #'[nzcv], '[cond]", + {"ccmn_32_condcmp_imm"_h, + "ccmn_64_condcmp_imm"_h, + "ccmp_32_condcmp_imm"_h, + "ccmp_64_condcmp_imm"_h}}, + {"'Rn, 'ITri", {"tst_ands_32s_log_imm"_h, "tst_ands_64s_log_imm"_h}}, + {"'Rn, 'Rm, #'[nzcv], '[cond]", + {"ccmn_32_condcmp_reg"_h, + "ccmn_64_condcmp_reg"_h, + "ccmp_32_condcmp_reg"_h, + "ccmp_64_condcmp_reg"_h}}, + {"'Rn, 'Rm'(1510?, '[shift] #'u1510)", + {"cmn_adds_32_addsub_shift"_h, + "cmn_adds_64_addsub_shift"_h, + "cmp_subs_32_addsub_shift"_h, + "cmp_subs_64_addsub_shift"_h, + "tst_ands_32_log_shift"_h, + "tst_ands_64_log_shift"_h}}, + {"'Rns, '(1413=3?x:w)'(2016=31?zr:'u2016)'(1510=16?'$:, '[ext32])'(1210? " + "#'u1210)", + {"cmn_adds_32s_addsub_ext"_h, "cmp_subs_32s_addsub_ext"_h}}, + {"'Rns, '(1413=3?x:w)'(2016=31?zr:'u2016)'(1510=16?'$:, '[ext64])'(1210? " + "#'u1210)", + {"cmn_adds_64s_addsub_ext"_h, "cmp_subs_64s_addsub_ext"_h}}, + {"'Rns, #0x'(22?':'x2110) ('(22?':'u2110))", + {"cmn_adds_32s_addsub_imm"_h, + "cmn_adds_64s_addsub_imm"_h, + "cmp_subs_32s_addsub_imm"_h, + "cmp_subs_64s_addsub_imm"_h}}, + {"'Rt, #'u31_2319, 'TImmTest", + {"tbnz_only_testbranch"_h, "tbz_only_testbranch"_h}}, + {"'Rt, 'TImmCmpa", + {"cbnz_32_compbranch"_h, + "cbnz_64_compbranch"_h, + "cbz_32_compbranch"_h, + "cbz_64_compbranch"_h}}, + {"'Sd, 'Dn", {"fcvt_sd_floatdp1"_h, "fcvtxn_asisdmisc_n"_h}}, + {"'Sd, 'Hn", {"fcvt_sh_floatdp1"_h}}, + {"'Sd, #'f2013", {"fmov_s_floatimm"_h}}, + {"'Sd, 'Sn", {"sha1h_ss_cryptosha2"_h}}, + {"'Sd, 'Vn.4s", + {"fmaxnmv_asimdall_only_sd"_h, + "fminnmv_asimdall_only_sd"_h, + "fmaxv_asimdall_only_sd"_h, + "fminv_asimdall_only_sd"_h}}, + {"'St, pc'(23?:+)' 'LValue", {"ldr_s_loadlit"_h}}, + {"'St, 'St2, ['Xns'(2115?, #')]", + {"ldnp_s_ldstnapair_offs"_h, + "ldp_s_ldstpair_off"_h, + "stnp_s_ldstnapair_offs"_h, + "stp_s_ldstpair_off"_h}}, + {"'St, 'St2, ['Xns, #']!", + {"ldp_s_ldstpair_pre"_h, "stp_s_ldstpair_pre"_h}}, + {"'St, 'St2, ['Xns], #'", + {"ldp_s_ldstpair_post"_h, "stp_s_ldstpair_post"_h}}, + {"'St, ['Xns'(2012?, #'s2012)]", + {"ldur_s_ldst_unscaled"_h, "stur_s_ldst_unscaled"_h}}, + {"'St, ['Xns'(2110?, #')]", + {"ldr_s_ldst_pos"_h, "str_s_ldst_pos"_h}}, + {"'St, ['Xns, #'s2012]!", {"ldr_s_ldst_immpre"_h, "str_s_ldst_immpre"_h}}, + {"'St, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #2)]", + {"ldr_s_ldst_regoff"_h, "str_s_ldst_regoff"_h}}, + {"'St, ['Xns], #'s2012", + {"ldr_s_ldst_immpost"_h, "str_s_ldst_immpost"_h}}, + {"'TImmCond", + {"b.'[condb]_b_only_condbranch"_h, "bc.'[condb]_bc_only_condbranch"_h}}, + {"'TImmUncn", {"b_only_branch_imm"_h, "bl_only_branch_imm"_h}}, + {"'Vd.'[nf], 'Vn.'[nf], 'Vm.'[nf]", + {"fabd_asimdsame_only"_h, "facge_asimdsame_only"_h, + "facgt_asimdsame_only"_h, "faddp_asimdsame_only"_h, + "fadd_asimdsame_only"_h, "fcmeq_asimdsame_only"_h, + "fcmge_asimdsame_only"_h, "fcmgt_asimdsame_only"_h, + "fdiv_asimdsame_only"_h, "fmaxnmp_asimdsame_only"_h, + "fmaxnm_asimdsame_only"_h, "fmaxp_asimdsame_only"_h, + "fmax_asimdsame_only"_h, "fminnmp_asimdsame_only"_h, + "fminnm_asimdsame_only"_h, "fminp_asimdsame_only"_h, + "fmin_asimdsame_only"_h, "fmla_asimdsame_only"_h, + "fmls_asimdsame_only"_h, "fmulx_asimdsame_only"_h, + "fmul_asimdsame_only"_h, "frecps_asimdsame_only"_h, + "frsqrts_asimdsame_only"_h, "fsub_asimdsame_only"_h}}, + {"'Vd.'[nf], 'Vn.'[nf], 'Vf.'[sz][']", + {"fmla_asimdelem_r_sd"_h, + "fmls_asimdelem_r_sd"_h, + "fmulx_asimdelem_r_sd"_h, + "fmul_asimdelem_r_sd"_h}}, + {"'Vd.'[npair], 'Vn.'[n]", + {"sadalp_asimdmisc_p"_h, + "saddlp_asimdmisc_p"_h, + "uadalp_asimdmisc_p"_h, + "uaddlp_asimdmisc_p"_h}}, + {"'Vd.'[nshift], 'Vn.'[nshift], #'", + {"sqshlu_asimdshf_r"_h, + "sqshl_asimdshf_r"_h, + "uqshl_asimdshf_r"_h, + "shl_asimdshf_r"_h, + "sli_asimdshf_r"_h}}, + {"'Vd.'[nshift], 'Vn.'[nshift], #'<16 31 u2219 clz32 - lsl u2216 ->", + {"sri_asimdshf_r"_h, + "srshr_asimdshf_r"_h, + "srsra_asimdshf_r"_h, + "sshr_asimdshf_r"_h, + "ssra_asimdshf_r"_h, + "urshr_asimdshf_r"_h, + "ursra_asimdshf_r"_h, + "ushr_asimdshf_r"_h, + "usra_asimdshf_r"_h, + "scvtf_asimdshf_c"_h, + "ucvtf_asimdshf_c"_h, + "fcvtzs_asimdshf_c"_h, + "fcvtzu_asimdshf_c"_h}}, + {"'Vd.'[nshift], 'Vn.'[nshiftln], #'<16 31 u2219 clz32 - lsl u2216 ->", + {"shrn_asimdshf_n"_h, + "rshrn_asimdshf_n"_h, + "sqshrn_asimdshf_n"_h, + "sqrshrn_asimdshf_n"_h, + "sqshrun_asimdshf_n"_h, + "sqrshrun_asimdshf_n"_h, + "uqshrn_asimdshf_n"_h, + "uqrshrn_asimdshf_n"_h, + "shrn2_shrn_asimdshf_n"_h, + "rshrn2_rshrn_asimdshf_n"_h, + "sqshrn2_sqshrn_asimdshf_n"_h, + "sqrshrn2_sqrshrn_asimdshf_n"_h, + "sqshrun2_sqshrun_asimdshf_n"_h, + "sqrshrun2_sqrshrun_asimdshf_n"_h, + "uqshrn2_uqshrn_asimdshf_n"_h, + "uqrshrn2_uqrshrn_asimdshf_n"_h}}, + {"'Vd.'[nshiftln], 'Vn.'[nshift]", + {"sxtl_sshll_asimdshf_l"_h, + "uxtl_ushll_asimdshf_l"_h, + "sxtl2_sshll_asimdshf_l"_h, + "uxtl2_ushll_asimdshf_l"_h}}, + {"'Vd.'[nshiftln], 'Vn.'[nshift], #'", + {"sshll_asimdshf_l"_h, + "ushll_asimdshf_l"_h, + "sshll2_sshll_asimdshf_l"_h, + "ushll2_ushll_asimdshf_l"_h}}, + {"'Vd.'[ntri], '(1916=8?'Xn:'Wn)", {"dup_asimdins_dr_r"_h}}, + {"'Vd.'[ntri], 'Vn.'[ntriscal][']", + {"dup_asimdins_dv_v"_h}}, + {"'Vd.'[ntriscal]['], '(1916=8?'Xn:'Wn)", + {"mov_ins_asimdins_ir_r"_h}}, + {"'Vd.'[ntriscal]['], 'Vn.'[ntriscal][']", + {"mov_ins_asimdins_iv_v"_h}}, + {"'Vd.'(22?1q:8h), 'Vn.'(22?'d:'b), " + "'Vm.'(22?'d:'b)", + {"pmull_asimddiff_l"_h, "pmull2_pmull_asimddiff_l"_h}}, + {"'Vd.'(22?2d:4s), 'Vn.'(22?2s:4h)", {"fcvtl_asimdmisc_l"_h}}, + {"'Vd.'(22?2d:4s), 'Vn.'(22?4s:8h)", {"fcvtl2_fcvtl_asimdmisc_l"_h}}, + {"'Vd.'(22?2s:4h), 'Vn.'(22?2d:4s)", {"fcvtn_asimdmisc_n"_h}}, + {"'Vd.'(22?4s:8h), 'Vn.'(22?2d:4s)", {"fcvtn2_fcvtn_asimdmisc_n"_h}}, + {"'Vd.'(22?4s:2d), 'Vn.'[n], 'Vf.'[sz][']", + {"smlal_asimdelem_l"_h, + "smlsl_asimdelem_l"_h, + "smull_asimdelem_l"_h, + "umlal_asimdelem_l"_h, + "umlsl_asimdelem_l"_h, + "umull_asimdelem_l"_h, + "sqdmull_asimdelem_l"_h, + "sqdmlal_asimdelem_l"_h, + "sqdmlsl_asimdelem_l"_h, + "smlal2_smlal_asimdelem_l"_h, + "smlsl2_smlsl_asimdelem_l"_h, + "smull2_smull_asimdelem_l"_h, + "umlal2_umlal_asimdelem_l"_h, + "umlsl2_umlsl_asimdelem_l"_h, + "umull2_umull_asimdelem_l"_h, + "sqdmull2_sqdmull_asimdelem_l"_h, + "sqdmlal2_sqdmlal_asimdelem_l"_h, + "sqdmlsl2_sqdmlsl_asimdelem_l"_h}}, + {"'Vd.'(2222=1?2d:'?30:42s), 'Vn.'(2222=1?2d:'?30:42s)", + {"fabs_asimdmisc_r"_h, "fcvtas_asimdmisc_r"_h, + "fcvtau_asimdmisc_r"_h, "fcvtms_asimdmisc_r"_h, + "fcvtmu_asimdmisc_r"_h, "fcvtns_asimdmisc_r"_h, + "fcvtnu_asimdmisc_r"_h, "fcvtps_asimdmisc_r"_h, + "fcvtpu_asimdmisc_r"_h, "fcvtzs_asimdmisc_r"_h, + "fcvtzu_asimdmisc_r"_h, "fneg_asimdmisc_r"_h, + "frecpe_asimdmisc_r"_h, "frint32x_asimdmisc_r"_h, + "frint32z_asimdmisc_r"_h, "frint64x_asimdmisc_r"_h, + "frint64z_asimdmisc_r"_h, "frinta_asimdmisc_r"_h, + "frinti_asimdmisc_r"_h, "frintm_asimdmisc_r"_h, + "frintn_asimdmisc_r"_h, "frintp_asimdmisc_r"_h, + "frintx_asimdmisc_r"_h, "frintz_asimdmisc_r"_h, + "frsqrte_asimdmisc_r"_h, "fsqrt_asimdmisc_r"_h, + "scvtf_asimdmisc_r"_h, "ucvtf_asimdmisc_r"_h}}, + {"'Vd.'(2222=1?2d:'?30:42s), 'Vn.'(2222=1?2d:'?30:42s), #0.0", + {"fcmeq_asimdmisc_fz"_h, + "fcmge_asimdmisc_fz"_h, + "fcmgt_asimdmisc_fz"_h, + "fcmle_asimdmisc_fz"_h, + "fcmlt_asimdmisc_fz"_h}}, + {"'Vd.'(30?16:8)b, 'Vn.'(30?16:8)b", + {"rbit_asimdmisc_r"_h, + "cnt_asimdmisc_r"_h, + "rev16_asimdmisc_r"_h, + "mov_orr_asimdsame_only"_h, + "mvn_not_asimdmisc_r"_h}}, + {"'Vd.'(30?16:8)b, 'Vn.'(30?16:8)b, 'Vm.'(30?16:8)b", + {"and_asimdsame_only"_h, + "bic_asimdsame_only"_h, + "bif_asimdsame_only"_h, + "bit_asimdsame_only"_h, + "bsl_asimdsame_only"_h, + "eor_asimdsame_only"_h, + "orn_asimdsame_only"_h, + "orr_asimdsame_only"_h, + "pmul_asimdsame_only"_h}}, + {"'Vd.'(30?16:8)b, 'Vn.'(30?16:8)b, 'Vm.'(30?16:8)b, #'u1411", + {"ext_asimdext_only"_h}}, + {"'Vd.'(30?16:8)b, {'Vn.16b, 'Vn2.16b, 'Vn3.16b, 'Vn4.16b}, " + "'Vm.'(30?16:8)b", + {"tbl_asimdtbl_l4_4"_h, "tbx_asimdtbl_l4_4"_h}}, + {"'Vd.'(30?16:8)b, {'Vn.16b, 'Vn2.16b, 'Vn3.16b}, 'Vm.'(30?16:8)b", + {"tbl_asimdtbl_l3_3"_h, "tbx_asimdtbl_l3_3"_h}}, + {"'Vd.'(30?16:8)b, {'Vn.16b, 'Vn2.16b}, 'Vm.'(30?16:8)b", + {"tbl_asimdtbl_l2_2"_h, "tbx_asimdtbl_l2_2"_h}}, + {"'Vd.'(30?16:8)b, {'Vn.16b}, 'Vm.'(30?16:8)b", + {"tbl_asimdtbl_l1_1"_h, "tbx_asimdtbl_l1_1"_h}}, + {"'Vd.'?30:42s, 'Vn.'(30?16:8)b, 'Vm.4b['u11_21]", + {"sdot_asimdelem_d"_h, + "sudot_asimdelem_d"_h, + "udot_asimdelem_d"_h, + "usdot_asimdelem_d"_h}}, + {"'Vd.'?30:42s, 'Vn.'?30:42h, 'Ve.h['u11_2120]", + {"fmlal2_asimdelem_lh"_h, + "fmlal_asimdelem_lh"_h, + "fmlsl2_asimdelem_lh"_h, + "fmlsl_asimdelem_lh"_h}}, + {"'Vd.'?30:42s, 'Vn.'?30:42h, 'Vm.'?30:42h", + {"fmlal2_asimdsame_f"_h, + "fmlal_asimdsame_f"_h, + "fmlsl2_asimdsame_f"_h, + "fmlsl_asimdsame_f"_h}}, + {"'Vd.'?30:42s, 'Vn.'?30:84h, 'Vm.'?30:84h", + {"bfdot_asimdsame2_d"_h, "bfmmla_asimdsame2_e"_h}}, + {"'Vd.'?30:42s, 'Vn.'?30:84h, 'Vm.2h['u11_21]", {"bfdot_asimdelem_e"_h}}, + {"'Vd.'?30:42s, 'Vn.'?30:42s", + {"urecpe_asimdmisc_r"_h, "ursqrte_asimdmisc_r"_h}}, + {"'Vd.'?30:42s, 'Vn.'(30?16:8)b, 'Vm.'(30?16:8)b", + {"sdot_asimdsame2_d"_h, "udot_asimdsame2_d"_h, "usdot_asimdsame2_d"_h}}, + {"'Vd.'?30:42s, 'Vn.2d", + {"fcvtxn_asimdmisc_n"_h, "fcvtxn2_fcvtxn_asimdmisc_n"_h}}, + {"'Vd.'?30:84h, 'Vn.4s", + {"bfcvtn_asimdmisc_4s"_h, "bfcvtn2_bfcvtn_asimdmisc_4s"_h}}, + {"'Vd.'?30:84h, 'Vn.'?30:84h", + {"fabs_asimdmiscfp16_r"_h, "fcvtas_asimdmiscfp16_r"_h, + "fcvtau_asimdmiscfp16_r"_h, "fcvtms_asimdmiscfp16_r"_h, + "fcvtmu_asimdmiscfp16_r"_h, "fcvtns_asimdmiscfp16_r"_h, + "fcvtnu_asimdmiscfp16_r"_h, "fcvtps_asimdmiscfp16_r"_h, + "fcvtpu_asimdmiscfp16_r"_h, "fcvtzs_asimdmiscfp16_r"_h, + "fcvtzu_asimdmiscfp16_r"_h, "fneg_asimdmiscfp16_r"_h, + "frecpe_asimdmiscfp16_r"_h, "frinta_asimdmiscfp16_r"_h, + "frinti_asimdmiscfp16_r"_h, "frintm_asimdmiscfp16_r"_h, + "frintn_asimdmiscfp16_r"_h, "frintp_asimdmiscfp16_r"_h, + "frintx_asimdmiscfp16_r"_h, "frintz_asimdmiscfp16_r"_h, + "frsqrte_asimdmiscfp16_r"_h, "fsqrt_asimdmiscfp16_r"_h, + "scvtf_asimdmiscfp16_r"_h, "ucvtf_asimdmiscfp16_r"_h}}, + {"'Vd.'?30:84h, 'Vn.'?30:84h, #0.0", + {"fcmeq_asimdmiscfp16_fz"_h, + "fcmge_asimdmiscfp16_fz"_h, + "fcmgt_asimdmiscfp16_fz"_h, + "fcmle_asimdmiscfp16_fz"_h, + "fcmlt_asimdmiscfp16_fz"_h}}, + {"'Vd.'?30:84h, 'Vn.'?30:84h, 'Ve.h[']", + {"fmla_asimdelem_rh_h"_h, + "fmls_asimdelem_rh_h"_h, + "fmulx_asimdelem_rh_h"_h, + "fmul_asimdelem_rh_h"_h}}, + {"'Vd.'?30:84h, 'Vn.'?30:84h, 'Vm.'?30:84h", + {"fabd_asimdsamefp16_only"_h, "facge_asimdsamefp16_only"_h, + "facgt_asimdsamefp16_only"_h, "faddp_asimdsamefp16_only"_h, + "fadd_asimdsamefp16_only"_h, "fcmeq_asimdsamefp16_only"_h, + "fcmge_asimdsamefp16_only"_h, "fcmgt_asimdsamefp16_only"_h, + "fdiv_asimdsamefp16_only"_h, "fmaxnmp_asimdsamefp16_only"_h, + "fmaxnm_asimdsamefp16_only"_h, "fmaxp_asimdsamefp16_only"_h, + "fmax_asimdsamefp16_only"_h, "fminnmp_asimdsamefp16_only"_h, + "fminnm_asimdsamefp16_only"_h, "fminp_asimdsamefp16_only"_h, + "fmin_asimdsamefp16_only"_h, "fmla_asimdsamefp16_only"_h, + "fmls_asimdsamefp16_only"_h, "fmulx_asimdsamefp16_only"_h, + "fmul_asimdsamefp16_only"_h, "frecps_asimdsamefp16_only"_h, + "frsqrts_asimdsamefp16_only"_h, "fsub_asimdsamefp16_only"_h}}, + {"'Vd.'?30:84h, 'Vn.'?30:84h, 'Vm.h['], #'", + {"fcmla_asimdelem_c_h"_h}}, + {"'Vd.'[n], 'Vn.'[n]", + {"abs_asimdmisc_r"_h, "cls_asimdmisc_r"_h, "clz_asimdmisc_r"_h, + "neg_asimdmisc_r"_h, "not_asimdmisc_r"_h, "rev32_asimdmisc_r"_h, + "rev64_asimdmisc_r"_h, "sqabs_asimdmisc_r"_h, "sqneg_asimdmisc_r"_h, + "suqadd_asimdmisc_r"_h, "usqadd_asimdmisc_r"_h, "abs_asimdmisc_r"_h, + "cls_asimdmisc_r"_h, "clz_asimdmisc_r"_h, "cnt_asimdmisc_r"_h, + "neg_asimdmisc_r"_h, "rev16_asimdmisc_r"_h, "rev32_asimdmisc_r"_h, + "rev64_asimdmisc_r"_h, "sqabs_asimdmisc_r"_h, "sqneg_asimdmisc_r"_h, + "suqadd_asimdmisc_r"_h, "urecpe_asimdmisc_r"_h, "ursqrte_asimdmisc_r"_h, + "usqadd_asimdmisc_r"_h}}, + {"'Vd.'[n], 'Vn.'[n], #0", + {"cmeq_asimdmisc_z"_h, + "cmge_asimdmisc_z"_h, + "cmgt_asimdmisc_z"_h, + "cmle_asimdmisc_z"_h, + "cmlt_asimdmisc_z"_h}}, + {"'Vd.'[n], 'Vn.'[n], 'Vf.'[sz][']", + {"mla_asimdelem_r"_h, + "mls_asimdelem_r"_h, + "mul_asimdelem_r"_h, + "sqdmulh_asimdelem_r"_h, + "sqrdmlah_asimdelem_r"_h, + "sqrdmlsh_asimdelem_r"_h, + "sqrdmulh_asimdelem_r"_h}}, + {"'Vd.'[n], 'Vn.'[n], 'Vm.'[n]", + {"mla_asimdsame_only"_h, "mls_asimdsame_only"_h, + "mul_asimdsame_only"_h, "saba_asimdsame_only"_h, + "sabd_asimdsame_only"_h, "shadd_asimdsame_only"_h, + "shsub_asimdsame_only"_h, "smaxp_asimdsame_only"_h, + "smax_asimdsame_only"_h, "sminp_asimdsame_only"_h, + "smin_asimdsame_only"_h, "srhadd_asimdsame_only"_h, + "uaba_asimdsame_only"_h, "uabd_asimdsame_only"_h, + "uhadd_asimdsame_only"_h, "uhsub_asimdsame_only"_h, + "umaxp_asimdsame_only"_h, "umax_asimdsame_only"_h, + "uminp_asimdsame_only"_h, "umin_asimdsame_only"_h, + "urhadd_asimdsame_only"_h, "addp_asimdsame_only"_h, + "add_asimdsame_only"_h, "cmeq_asimdsame_only"_h, + "cmge_asimdsame_only"_h, "cmgt_asimdsame_only"_h, + "cmhi_asimdsame_only"_h, "cmhs_asimdsame_only"_h, + "cmtst_asimdsame_only"_h, "sqadd_asimdsame_only"_h, + "sqdmulh_asimdsame_only"_h, "sqrdmulh_asimdsame_only"_h, + "sqrshl_asimdsame_only"_h, "sqshl_asimdsame_only"_h, + "sqsub_asimdsame_only"_h, "srshl_asimdsame_only"_h, + "sshl_asimdsame_only"_h, "sub_asimdsame_only"_h, + "uqadd_asimdsame_only"_h, "uqrshl_asimdsame_only"_h, + "uqshl_asimdsame_only"_h, "uqsub_asimdsame_only"_h, + "urshl_asimdsame_only"_h, "ushl_asimdsame_only"_h, + "trn1_asimdperm_only"_h, "trn2_asimdperm_only"_h, + "uzp1_asimdperm_only"_h, "uzp2_asimdperm_only"_h, + "zip1_asimdperm_only"_h, "zip2_asimdperm_only"_h, + "sqrdmlah_asimdsame2_only"_h, "sqrdmlsh_asimdsame2_only"_h}}, + {"'Vd.'[n], 'Vn.'[n], 'Vm.'[n], #'", + {"fcmla_asimdsame2_c"_h}}, + {"'Vd.'[n], 'Vn.'[n], 'Vm.'[n], #'(12?270:90)", {"fcadd_asimdsame2_c"_h}}, + {"'Vd.'[n], 'Vn.'[nl]", + {"xtn_asimdmisc_n"_h, + "sqxtn_asimdmisc_n"_h, + "uqxtn_asimdmisc_n"_h, + "sqxtun_asimdmisc_n"_h, + "xtn2_xtn_asimdmisc_n"_h, + "sqxtn2_sqxtn_asimdmisc_n"_h, + "uqxtn2_uqxtn_asimdmisc_n"_h, + "sqxtun2_sqxtun_asimdmisc_n"_h}}, + {"'Vd.'[n], 'Vn.'[nl], 'Vm.'[nl]", + {"addhn_asimddiff_n"_h, + "raddhn_asimddiff_n"_h, + "rsubhn_asimddiff_n"_h, + "subhn_asimddiff_n"_h, + "addhn2_addhn_asimddiff_n"_h, + "raddhn2_raddhn_asimddiff_n"_h, + "rsubhn2_rsubhn_asimddiff_n"_h, + "subhn2_subhn_asimddiff_n"_h}}, + {"'Vd.'[nl], 'Vn.'[n], #'(2322?':8)", + {"shll_asimdmisc_s"_h, "shll2_shll_asimdmisc_s"_h}}, + {"'Vd.'[nl], 'Vn.'[n], 'Vm.'[n]", + {"sabal_asimddiff_l"_h, + "sabdl_asimddiff_l"_h, + "saddl_asimddiff_l"_h, + "smlal_asimddiff_l"_h, + "smlsl_asimddiff_l"_h, + "smull_asimddiff_l"_h, + "ssubl_asimddiff_l"_h, + "uabal_asimddiff_l"_h, + "uabdl_asimddiff_l"_h, + "uaddl_asimddiff_l"_h, + "umlal_asimddiff_l"_h, + "umlsl_asimddiff_l"_h, + "umull_asimddiff_l"_h, + "usubl_asimddiff_l"_h, + "sabal2_sabal_asimddiff_l"_h, + "sabdl2_sabdl_asimddiff_l"_h, + "saddl2_saddl_asimddiff_l"_h, + "smlal2_smlal_asimddiff_l"_h, + "smlsl2_smlsl_asimddiff_l"_h, + "smull2_smull_asimddiff_l"_h, + "ssubl2_ssubl_asimddiff_l"_h, + "uabal2_uabal_asimddiff_l"_h, + "uabdl2_uabdl_asimddiff_l"_h, + "uaddl2_uaddl_asimddiff_l"_h, + "umlal2_umlal_asimddiff_l"_h, + "umlsl2_umlsl_asimddiff_l"_h, + "umull2_umull_asimddiff_l"_h, + "usubl2_usubl_asimddiff_l"_h, + "sqdmlal_asimddiff_l"_h, + "sqdmlsl_asimddiff_l"_h, + "sqdmull_asimddiff_l"_h, + "sqdmlal2_sqdmlal_asimddiff_l"_h, + "sqdmlsl2_sqdmlsl_asimddiff_l"_h, + "sqdmull2_sqdmull_asimddiff_l"_h}}, + {"'Vd.'[nl], 'Vn.'[nl], 'Vm.'[n]", + {"saddw_asimddiff_w"_h, + "ssubw_asimddiff_w"_h, + "uaddw_asimddiff_w"_h, + "usubw_asimddiff_w"_h, + "saddw2_saddw_asimddiff_w"_h, + "ssubw2_ssubw_asimddiff_w"_h, + "uaddw2_uaddw_asimddiff_w"_h, + "usubw2_usubw_asimddiff_w"_h}}, + {"'Vd.16b, 'Vn.16b", + {"aesd_b_cryptoaes"_h, + "aese_b_cryptoaes"_h, + "aesimc_b_cryptoaes"_h, + "aesmc_b_cryptoaes"_h}}, + {"'Vd.16b, 'Vn.16b, 'Vm.16b, 'Va.16b", + {"bcax_vvv16_crypto4"_h, "eor3_vvv16_crypto4"_h}}, + {"'Vd.2d, 'Vn.2d", {"sha512su0_vv2_cryptosha512_2"_h}}, + {"'Vd.2d, 'Vn.2d, 'Vm.2d", + {"rax1_vvv2_cryptosha512_3"_h, "sha512su1_vvv2_cryptosha512_3"_h}}, + {"'Vd.2d, 'Vn.2d, 'Vm.2d, #'u1510", {"xar_vvv2_crypto3_imm6"_h}}, + {"'Vd.4s, 'Vn.16b, 'Vm.16b", + {"smmla_asimdsame2_g"_h, + "ummla_asimdsame2_g"_h, + "usmmla_asimdsame2_g"_h}}, + {"'Vd.4s, 'Vn.4s", + {"sha1su1_vv_cryptosha2"_h, + "sha256su0_vv_cryptosha2"_h, + "sm4e_vv4_cryptosha512_2"_h}}, + {"'Vd.4s, 'Vn.4s, 'Vm.4s", + {"sha1su0_vvv_cryptosha3"_h, + "sha256su1_vvv_cryptosha3"_h, + "sm3partw1_vvv4_cryptosha512_3"_h, + "sm3partw2_vvv4_cryptosha512_3"_h, + "sm4ekey_vvv4_cryptosha512_3"_h}}, + {"'Vd.4s, 'Vn.4s, 'Vm.4s, 'Va.4s", {"sm3ss1_vvv4_crypto4"_h}}, + {"'Vd.4s, 'Vn.4s, 'Vm.s['u1312]", + {"sm3tt1a_vvv4_crypto3_imm2"_h, + "sm3tt1b_vvv4_crypto3_imm2"_h, + "sm3tt2a_vvv4_crypto3_imm2"_h, + "sm3tt2b_vvv_crypto3_imm2"_h}}, + {"'Vd.4s, 'Vn.4s, 'Vm.s['], #'", + {"fcmla_asimdelem_c_s"_h}}, + {"'Vd.D[1], 'Rn", {"fmov_v64i_float2int"_h}}, + {"'Vdv, 'Pgl, 'Zn.'[sz]", + {"andv_r_p_z"_h, + "eorv_r_p_z"_h, + "orv_r_p_z"_h, + "smaxv_r_p_z"_h, + "sminv_r_p_z"_h, + "umaxv_r_p_z"_h, + "uminv_r_p_z"_h}}, + {"'Vt.'(30?16:8)b, #0x'x1816_0905", {"movi_asimdimm_n_b"_h}}, + {"'Vt.'?30:42s, #0x'x1816_0905'(1413?, lsl #')", + {"bic_asimdimm_l_sl"_h, + "movi_asimdimm_l_sl"_h, + "mvni_asimdimm_l_sl"_h, + "orr_asimdimm_l_sl"_h}}, + {"'Vt.'?30:42s, #0x'x1816_0905, msl #'(12?16:8)", + {"movi_asimdimm_m_sm"_h, "mvni_asimdimm_m_sm"_h}}, + {"'Vt.'?30:42s, #'f1816_0905", {"fmov_asimdimm_s_s"_h}}, + {"'Vt.'?30:84h, #0x'x1816_0905'(1413?, lsl #')", + {"bic_asimdimm_l_hl"_h, + "movi_asimdimm_l_hl"_h, + "mvni_asimdimm_l_hl"_h, + "orr_asimdimm_l_hl"_h}}, + {"'Vt.'?30:84h, #'f1816_0905", {"fmov_asimdimm_h_h"_h}}, + {"'Vt.2d, #'f1816_0905", {"fmov_asimdimm_d2_d"_h}}, + {"'Vt.2d, #0x'<0xff 56 lsl u18 * 0xff 48 lsl u17 * + 0xff 40 lsl u16 * + " + "0xff 32 lsl u09 * + 0xff 24 lsl u08 * + 0xff0000 u07 * + 0xff00 u06 * " + "+ 0xff u05 * + hex>", + {"movi_asimdimm_d2_d"_h}}, + {"'Wd, 'Pn.'[sz]", {"uqdecp_r_p_r_uw"_h, "uqincp_r_p_r_uw"_h}}, + {"'Wd, 'Wn, 'Xm", {"crc32cx_64c_dp_2src"_h, "crc32x_64c_dp_2src"_h}}, + {"'Wn", {"setf16_only_setf"_h, "setf8_only_setf"_h}}, + {"'Wt, pc'(23?:+)' 'LValue", {"ldr_32_loadlit"_h}}, + {"'Wt, 'Wt2, ['Xns]", {"ldxp_lp32_ldstexcl"_h, "ldaxp_lp32_ldstexcl"_h}}, + {"'Wt, 'Wt2, ['Xns'(2115?, #')]", + {"ldnp_32_ldstnapair_offs"_h, + "ldp_32_ldstpair_off"_h, + "stnp_32_ldstnapair_offs"_h, + "stp_32_ldstpair_off"_h}}, + {"'Wt, 'Wt2, ['Xns, #']!", + {"ldp_32_ldstpair_pre"_h, "stp_32_ldstpair_pre"_h}}, + {"'Wt, 'Wt2, ['Xns], #'", + {"ldp_32_ldstpair_post"_h, "stp_32_ldstpair_post"_h}}, + {"'Wt, ['Xns'(2012?, #'s2012)]", + {"ldapur_32_ldapstl_unscaled"_h, "ldapurb_32_ldapstl_unscaled"_h, + "ldapurh_32_ldapstl_unscaled"_h, "ldapursb_32_ldapstl_unscaled"_h, + "ldapursh_32_ldapstl_unscaled"_h, "ldur_32_ldst_unscaled"_h, + "ldurb_32_ldst_unscaled"_h, "ldurh_32_ldst_unscaled"_h, + "ldursb_32_ldst_unscaled"_h, "ldursh_32_ldst_unscaled"_h, + "stlur_32_ldapstl_unscaled"_h, "stlurb_32_ldapstl_unscaled"_h, + "stlurh_32_ldapstl_unscaled"_h, "stur_32_ldst_unscaled"_h, + "sturb_32_ldst_unscaled"_h, "sturh_32_ldst_unscaled"_h, + "ldtr_32_ldst_unpriv"_h, "ldtrb_32_ldst_unpriv"_h, + "ldtrh_32_ldst_unpriv"_h, "ldtrsb_32_ldst_unpriv"_h, + "ldtrsh_32_ldst_unpriv"_h, "sttr_32_ldst_unpriv"_h, + "sttrb_32_ldst_unpriv"_h, "sttrh_32_ldst_unpriv"_h}}, + {"'Wt, ['Xns'(2110?, #'u2110)]", + {"ldrb_32_ldst_pos"_h, "ldrsb_32_ldst_pos"_h, "strb_32_ldst_pos"_h}}, + {"'Wt, ['Xns'(2110?, #')]", + {"ldrh_32_ldst_pos"_h, "ldrsh_32_ldst_pos"_h, "strh_32_ldst_pos"_h}}, + {"'Wt, ['Xns'(2110?, #')]", + {"ldr_32_ldst_pos"_h, "str_32_ldst_pos"_h}}, + {"'Wt, ['Xns, #'s2012]!", + {"ldr_32_ldst_immpre"_h, + "ldrb_32_ldst_immpre"_h, + "ldrh_32_ldst_immpre"_h, + "ldrsb_32_ldst_immpre"_h, + "ldrsh_32_ldst_immpre"_h, + "str_32_ldst_immpre"_h, + "strb_32_ldst_immpre"_h, + "strh_32_ldst_immpre"_h}}, + {"'Wt, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #'u3130)]", + {"ldrb_32b_ldst_regoff"_h, + "ldrb_32bl_ldst_regoff"_h, + "ldrsb_32b_ldst_regoff"_h, + "ldrsb_32bl_ldst_regoff"_h, + "strb_32b_ldst_regoff"_h, + "strb_32bl_ldst_regoff"_h, + "ldrh_32_ldst_regoff"_h, + "ldrsh_32_ldst_regoff"_h, + "strh_32_ldst_regoff"_h, + "ldr_32_ldst_regoff"_h, + "str_32_ldst_regoff"_h}}, + {"'Wt, ['Xns], #'s2012", + {"ldr_32_ldst_immpost"_h, + "ldrb_32_ldst_immpost"_h, + "ldrh_32_ldst_immpost"_h, + "ldrsb_32_ldst_immpost"_h, + "ldrsh_32_ldst_immpost"_h, + "str_32_ldst_immpost"_h, + "strb_32_ldst_immpost"_h, + "strh_32_ldst_immpost"_h}}, + {"'Xd", + {"autdza_64z_dp_1src"_h, + "autdzb_64z_dp_1src"_h, + "autiza_64z_dp_1src"_h, + "autizb_64z_dp_1src"_h, + "pacdza_64z_dp_1src"_h, + "pacdzb_64z_dp_1src"_h, + "paciza_64z_dp_1src"_h, + "pacizb_64z_dp_1src"_h, + "xpacd_64z_dp_1src"_h, + "xpaci_64z_dp_1src"_h}}, + {"'Xd'(1916?, '[mulpat], mul #''$)'(0905=31?:, '[mulpat])", + {"decb_r_rs"_h, + "decd_r_rs"_h, + "dech_r_rs"_h, + "decw_r_rs"_h, + "incb_r_rs"_h, + "incd_r_rs"_h, + "inch_r_rs"_h, + "incw_r_rs"_h, + "cntb_r_s"_h, + "cntd_r_s"_h, + "cnth_r_s"_h, + "cntw_r_s"_h}}, + {"'Xd, #'s1005", {"rdvl_r_i"_h}}, + {"'Xd, 'AddrPCRelByte", {"adr_only_pcreladdr"_h}}, + {"'Xd, 'AddrPCRelPage", {"adrp_only_pcreladdr"_h}}, + {"'Xd, 'Pn.'[sz]", + {"decp_r_p_r"_h, + "incp_r_p_r"_h, + "sqdecp_r_p_r_x"_h, + "sqincp_r_p_r_x"_h, + "uqdecp_r_p_r_x"_h, + "uqincp_r_p_r_x"_h}}, + {"'Xd, 'Pn.'[sz], 'Wd", {"sqdecp_r_p_r_sx"_h, "sqincp_r_p_r_sx"_h}}, + {"'Xd, 'Vn.'[ntriscal][']", + {"mov_umov_asimdins_x_x"_h, "smov_asimdins_x_x"_h}}, + {"'Wd, 'Vn.'[ntriscal][']", + {"mov_umov_asimdins_w_w"_h, + "umov_asimdins_w_w"_h, + "smov_asimdins_w_w"_h}}, + {"'Xd, 'Wd'(1916?, '[mulpat], mul #''$)'(0905=31?:, " + "'[mulpat])", + {"sqdecb_r_rs_sx"_h, + "sqdecd_r_rs_sx"_h, + "sqdech_r_rs_sx"_h, + "sqdecw_r_rs_sx"_h, + "sqincb_r_rs_sx"_h, + "sqincd_r_rs_sx"_h, + "sqinch_r_rs_sx"_h, + "sqincw_r_rs_sx"_h}}, + {"'Xd, 'Wn, 'Wm", + {"smull_smaddl_64wa_dp_3src"_h, + "smnegl_smsubl_64wa_dp_3src"_h, + "umull_umaddl_64wa_dp_3src"_h, + "umnegl_umsubl_64wa_dp_3src"_h}}, + {"'Xd, 'Wn, 'Wm, 'Xa", + {"smaddl_64wa_dp_3src"_h, + "smsubl_64wa_dp_3src"_h, + "umaddl_64wa_dp_3src"_h, + "umsubl_64wa_dp_3src"_h}}, + {"'Xd, 'Xn, 'Xm", {"smulh_64_dp_3src"_h, "umulh_64_dp_3src"_h}}, + {"'Xd, 'Xn, 'Xms", {"pacga_64p_dp_2src"_h}}, + {"'Xd, 'Xns", + {"autda_64p_dp_1src"_h, + "autdb_64p_dp_1src"_h, + "autia_64p_dp_1src"_h, + "autib_64p_dp_1src"_h, + "pacda_64p_dp_1src"_h, + "pacdb_64p_dp_1src"_h, + "pacia_64p_dp_1src"_h, + "pacib_64p_dp_1src"_h}}, + {"'Xd, 'Xns, 'Xms", {"subp_64s_dp_2src"_h, "subps_64s_dp_2src"_h}}, + {"'Xd, p'u1310, 'Pn.'[sz]", {"cntp_r_p_p"_h}}, + {"'Xds, 'Xms, #'s1005", {"addpl_r_ri"_h, "addvl_r_ri"_h}}, + {"'Xds, 'Xns'(2016=31?:, 'Xm)", {"irg_64i_dp_2src"_h}}, + {"'Xds, 'Xns, #', #'u1310", + {"addg_64_addsub_immtags"_h, "subg_64_addsub_immtags"_h}}, + {"'Xds, ['Xns'(2012?, #')]", + {"st2g_64soffset_ldsttags"_h, + "stg_64soffset_ldsttags"_h, + "stz2g_64soffset_ldsttags"_h, + "stzg_64soffset_ldsttags"_h}}, + {"'Xds, ['Xns, #']!", + {"st2g_64spre_ldsttags"_h, + "stg_64spre_ldsttags"_h, + "stz2g_64spre_ldsttags"_h, + "stzg_64spre_ldsttags"_h}}, + {"'Xds, ['Xns], #'", + {"st2g_64spost_ldsttags"_h, + "stg_64spost_ldsttags"_h, + "stz2g_64spost_ldsttags"_h, + "stzg_64spost_ldsttags"_h}}, + {"'Xn", + {"blr_64_branch_reg"_h, + "blraaz_64_branch_reg"_h, + "blrabz_64_branch_reg"_h, + "br_64_branch_reg"_h, + "braaz_64_branch_reg"_h, + "brabz_64_branch_reg"_h, + "drps_64e_branch_reg"_h, + "eret_64e_branch_reg"_h, + "eretaa_64e_branch_reg"_h, + "eretab_64e_branch_reg"_h}}, + {"'Xn, #'u2015, #'[nzcv]", {"rmif_only_rmif"_h}}, + {"'Xn, 'Xds", + {"blraa_64p_branch_reg"_h, + "blrab_64p_branch_reg"_h, + "braa_64p_branch_reg"_h, + "brab_64p_branch_reg"_h}}, + {"'Xns, 'Xms", {"cmpp_subps_64s_dp_2src"_h}}, + {"'Xt", + {"gcsss1_sys_cr_systeminstrs"_h, + "gcspushm_sys_cr_systeminstrs"_h, + "gcsss2_sysl_rc_systeminstrs"_h}}, + {"'Xt, pc'(23?:+)' 'LValue", + {"ldr_64_loadlit"_h, "ldrsw_64_loadlit"_h}}, + {"'Xt, 'IY", {"mrs_rs_systemmove"_h}}, + {"'Xt, 'Xt2, ['Xns]", {"ldxp_lp64_ldstexcl"_h, "ldaxp_lp64_ldstexcl"_h}}, + {"'Xt, 'Xt2, ['Xns'(2115?, #')]", {"stgp_64_ldstpair_off"_h}}, + {"'Xt, 'Xt2, ['Xns'(2115?, #')]", {"ldpsw_64_ldstpair_off"_h}}, + {"'Xt, 'Xt2, ['Xns'(2115?, #')]", + {"ldnp_64_ldstnapair_offs"_h, + "ldp_64_ldstpair_off"_h, + "stnp_64_ldstnapair_offs"_h, + "stp_64_ldstpair_off"_h}}, + {"'Xt, 'Xt2, ['Xns, #']!", {"stgp_64_ldstpair_pre"_h}}, + {"'Xt, 'Xt2, ['Xns, #']!", {"ldpsw_64_ldstpair_pre"_h}}, + {"'Xt, 'Xt2, ['Xns, #']!", + {"ldp_64_ldstpair_pre"_h, "stp_64_ldstpair_pre"_h}}, + {"'Xt, 'Xt2, ['Xns], #'", {"stgp_64_ldstpair_post"_h}}, + {"'Xt, 'Xt2, ['Xns], #'", {"ldpsw_64_ldstpair_post"_h}}, + {"'Xt, 'Xt2, ['Xns], #'", + {"ldp_64_ldstpair_post"_h, "stp_64_ldstpair_post"_h}}, + {"'Xt, ['Xns'(2012?, #'s2012)]", + {"ldapur_64_ldapstl_unscaled"_h, + "ldapursb_64_ldapstl_unscaled"_h, + "ldapursh_64_ldapstl_unscaled"_h, + "ldapursw_64_ldapstl_unscaled"_h, + "ldur_64_ldst_unscaled"_h, + "ldursb_64_ldst_unscaled"_h, + "ldursh_64_ldst_unscaled"_h, + "ldursw_64_ldst_unscaled"_h, + "stlur_64_ldapstl_unscaled"_h, + "stur_64_ldst_unscaled"_h, + "ldtr_64_ldst_unpriv"_h, + "ldtrsb_64_ldst_unpriv"_h, + "ldtrsh_64_ldst_unpriv"_h, + "ldtrsw_64_ldst_unpriv"_h, + "sttr_64_ldst_unpriv"_h}}, + {"'Xt, ['Xns'(2012?, #')]", {"ldg_64loffset_ldsttags"_h}}, + {"'Xt, ['Xns'(2212=512?:, #')]!", + {"ldraa_64w_ldst_pac"_h, "ldrab_64w_ldst_pac"_h}}, + {"'Xt, ['Xns'(2212=512?:, #')]", + {"ldraa_64_ldst_pac"_h, "ldrab_64_ldst_pac"_h}}, + {"'Xt, ['Xns'(2110?, #'u2110)]", {"ldrsb_64_ldst_pos"_h}}, + {"'Xt, ['Xns'(2110?, #')]", {"ldrsh_64_ldst_pos"_h}}, + {"'Xt, ['Xns'(2110?, #')]", {"ldrsw_64_ldst_pos"_h}}, + {"'Xt, ['Xns'(2110?, #')]", + {"ldr_64_ldst_pos"_h, "str_64_ldst_pos"_h}}, + {"'Xt, ['Xns, #'s2012]!", + {"ldr_64_ldst_immpre"_h, + "ldrsb_64_ldst_immpre"_h, + "ldrsh_64_ldst_immpre"_h, + "ldrsw_64_ldst_immpre"_h, + "str_64_ldst_immpre"_h}}, + {"'Xt, ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #'u3130)]", + {"ldrsb_64b_ldst_regoff"_h, + "ldrsb_64bl_ldst_regoff"_h, + "ldrsh_64_ldst_regoff"_h, + "ldrsw_64_ldst_regoff"_h, + "ldr_64_ldst_regoff"_h, + "str_64_ldst_regoff"_h}}, + {"'Xt, ['Xns], #'s2012", + {"ldr_64_ldst_immpost"_h, + "ldrsb_64_ldst_immpost"_h, + "ldrsh_64_ldst_immpost"_h, + "ldrsw_64_ldst_immpost"_h, + "str_64_ldst_immpost"_h}}, + {"'Xt, #'u1816, C'u1512, C'u1108, #'u0705", {"sysl_rc_systeminstrs"_h}}, + {"'Zd, 'Zn", {"movprfx_z_z"_h}}, + {"'Zd.'?22:ds, 'Zn.'?22:ds, 'Zm.'?22:ds", + {"adclb_z_zzz"_h, "adclt_z_zzz"_h, "sbclb_z_zzz"_h, "sbclt_z_zzz"_h}}, + {"'Zd.'[sz]'(1916?, '[mulpat], mul #''$)'(0905=31?:, " + "'[mulpat])", + {"decd_z_zs"_h, + "dech_z_zs"_h, + "decw_z_zs"_h, + "incd_z_zs"_h, + "inch_z_zs"_h, + "incw_z_zs"_h, + "sqdecd_z_zs"_h, + "sqdech_z_zs"_h, + "sqdecw_z_zs"_h, + "sqincd_z_zs"_h, + "sqinch_z_zs"_h, + "sqincw_z_zs"_h, + "uqdecd_z_zs"_h, + "uqdech_z_zs"_h, + "uqdecw_z_zs"_h, + "uqincd_z_zs"_h, + "uqinch_z_zs"_h, + "uqincw_z_zs"_h}}, + {"'Zd.'[sz], #'s0905, #'s2016", {"index_z_ii"_h}}, + {"'Zd.'[sz], #'s0905, '(2322=3?'Xm:'Wm)", {"index_z_ir"_h}}, + {"'Zd.'[sz], #'s1205'(13?, lsl #8)", {"mov_dup_z_i"_h}}, + {"'Zd.'[sz], '(2322=3?'Xn:'Wn)", {"insr_z_r"_h}}, + {"'Zd.'[sz], '(2322=3?'Xn:'Wn), #'s2016", {"index_z_ri"_h}}, + {"'Zd.'[sz], '(2322=3?'Xn:'Wn), '(2322=3?'Xm:'Wm)", {"index_z_rr"_h}}, + {"'Zd.'[sz], '(2322=3?'Xns:'Wns)", {"mov_dup_z_r"_h}}, + {"'Zd.'[sz], #'f1205", {"fmov_fdup_z_i"_h}}, + {"'Zd.'[sz], 'Pgl, 'Zd.'[sz], 'Zn.'[sz]", + {"clasta_z_p_zz"_h, "clastb_z_p_zz"_h, "splice_z_p_zz_des"_h}}, + {"'Zd.'[sz], 'Pgl, 'Zn.'[sz]", {"compact_z_p_z"_h}}, + {"'Zd.'[sz], 'Pgl, {'Zn.'[sz], 'Zn2.'[sz]}", {"splice_z_p_zz_con"_h}}, + {"'Zd.'[sz], 'Pgl/'?16:mz, 'Zn.'[sz]", {"movprfx_z_p_z"_h}}, + {"'Zd.'[sz], 'Pgl/m, '(2322=3?'Xns:'Wns)", {"mov_cpy_z_p_r"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Vnv", {"mov_cpy_z_p_v"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], #'(05?1:0).0", + {"fmaxnm_z_p_zs"_h, + "fmax_z_p_zs"_h, + "fminnm_z_p_zs"_h, + "fmin_z_p_zs"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], #'(05?1.0:0.5)", + {"fadd_z_p_zs"_h, "fsubr_z_p_zs"_h, "fsub_z_p_zs"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], #'(05?2.0:0.5)", {"fmul_z_p_zs"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], 'Zn.'[sz]", + {"addp_z_p_zz"_h, "shadd_z_p_zz"_h, "shsub_z_p_zz"_h, + "shsubr_z_p_zz"_h, "smaxp_z_p_zz"_h, "sminp_z_p_zz"_h, + "sqadd_z_p_zz"_h, "sqrshl_z_p_zz"_h, "sqrshlr_z_p_zz"_h, + "sqshl_z_p_zz"_h, "sqshlr_z_p_zz"_h, "sqsub_z_p_zz"_h, + "sqsubr_z_p_zz"_h, "srhadd_z_p_zz"_h, "srshl_z_p_zz"_h, + "srshlr_z_p_zz"_h, "suqadd_z_p_zz"_h, "uhadd_z_p_zz"_h, + "uhsub_z_p_zz"_h, "uhsubr_z_p_zz"_h, "umaxp_z_p_zz"_h, + "uminp_z_p_zz"_h, "uqadd_z_p_zz"_h, "uqrshl_z_p_zz"_h, + "uqrshlr_z_p_zz"_h, "uqshl_z_p_zz"_h, "uqshlr_z_p_zz"_h, + "uqsub_z_p_zz"_h, "uqsubr_z_p_zz"_h, "urhadd_z_p_zz"_h, + "urshl_z_p_zz"_h, "urshlr_z_p_zz"_h, "usqadd_z_p_zz"_h, + "mul_z_p_zz"_h, "smulh_z_p_zz"_h, "umulh_z_p_zz"_h, + "sabd_z_p_zz"_h, "smax_z_p_zz"_h, "smin_z_p_zz"_h, + "uabd_z_p_zz"_h, "umax_z_p_zz"_h, "umin_z_p_zz"_h, + "add_z_p_zz"_h, "subr_z_p_zz"_h, "sub_z_p_zz"_h, + "and_z_p_zz"_h, "bic_z_p_zz"_h, "eor_z_p_zz"_h, + "orr_z_p_zz"_h, "asrr_z_p_zz"_h, "asr_z_p_zz"_h, + "lslr_z_p_zz"_h, "lsl_z_p_zz"_h, "lsrr_z_p_zz"_h, + "lsr_z_p_zz"_h, "faddp_z_p_zz"_h, "fmaxnmp_z_p_zz"_h, + "fmaxp_z_p_zz"_h, "fminnmp_z_p_zz"_h, "fminp_z_p_zz"_h, + "fabd_z_p_zz"_h, "fadd_z_p_zz"_h, "fdivr_z_p_zz"_h, + "fdiv_z_p_zz"_h, "fmaxnm_z_p_zz"_h, "fmax_z_p_zz"_h, + "fminnm_z_p_zz"_h, "fmin_z_p_zz"_h, "fmulx_z_p_zz"_h, + "fmul_z_p_zz"_h, "fscale_z_p_zz"_h, "fsubr_z_p_zz"_h, + "fsub_z_p_zz"_h, "sdiv_z_p_zz"_h, "sdivr_z_p_zz"_h, + "udiv_z_p_zz"_h, "udivr_z_p_zz"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], 'Zn.'[sz], #'", + {"fcadd_z_p_zz"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zm.'[sz], 'Zn.'[sz]", + {"mad_z_p_zzz"_h, "msb_z_p_zzz"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zn.'[sz]", + {"sqabs_z_p_z"_h, "sqneg_z_p_z"_h, "frinta_z_p_z"_h, "frinti_z_p_z"_h, + "frintm_z_p_z"_h, "frintn_z_p_z"_h, "frintp_z_p_z"_h, "frintx_z_p_z"_h, + "frintz_z_p_z"_h, "frecpx_z_p_z"_h, "fsqrt_z_p_z"_h, "abs_z_p_z"_h, + "cls_z_p_z"_h, "clz_z_p_z"_h, "cnot_z_p_z"_h, "cnt_z_p_z"_h, + "fabs_z_p_z"_h, "fneg_z_p_z"_h, "neg_z_p_z"_h, "not_z_p_z"_h, + "sxtb_z_p_z"_h, "sxth_z_p_z"_h, "sxtw_z_p_z"_h, "uxtb_z_p_z"_h, + "uxth_z_p_z"_h, "uxtw_z_p_z"_h, "rbit_z_p_z"_h, "revb_z_z"_h, + "revh_z_z"_h, "revw_z_z"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zn.'[sz], 'Zm.'[sz]", + {"mla_z_p_zzz"_h, + "mls_z_p_zzz"_h, + "fmad_z_p_zzz"_h, + "fmla_z_p_zzz"_h, + "fmls_z_p_zzz"_h, + "fmsb_z_p_zzz"_h, + "fnmad_z_p_zzz"_h, + "fnmla_z_p_zzz"_h, + "fnmls_z_p_zzz"_h, + "fnmsb_z_p_zzz"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zn.'[sz], 'Zm.'[sz], #'", + {"fcmla_z_p_zzz"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zn.'[sszh]", {"sadalp_z_p_z"_h, "uadalp_z_p_z"_h}}, + {"'Zd.'[sz], 'Pgl/z, 'Zn.'[sz], 'Zm.'[sz]", {"histcnt_z_p_zz"_h}}, + {"'Zd.'[sz], 'Pm/'?14:mz, #'s1205'(13?, lsl #8)", + {"mov_cpy_z_o_i"_h, "mov_cpy_z_p_i"_h}}, + {"'Zd.'[sz], 'Pm/m, #'f1205", {"fmov_fcpy_z_p_i"_h}}, + {"'Zd.'[sz], 'Pn", + {"decp_z_p_z"_h, + "incp_z_p_z"_h, + "sqdecp_z_p_z"_h, + "sqincp_z_p_z"_h, + "uqdecp_z_p_z"_h, + "uqincp_z_p_z"_h}}, + {"'Zd.'[sz], 'Vnv", {"insr_z_v"_h}}, + {"'Zd.'[sz], 'Zd.'[sz], #'s1205", + {"mul_z_zi"_h, "smax_z_zi"_h, "smin_z_zi"_h}}, + {"'Zd.'[sz], 'Zd.'[sz], #'u1205", {"umax_z_zi"_h, "umin_z_zi"_h}}, + {"'Zd.'[sz], 'Zd.'[sz], #'u1205'(13?, lsl #8)", + {"add_z_zi"_h, + "sqadd_z_zi"_h, + "sqsub_z_zi"_h, + "sub_z_zi"_h, + "subr_z_zi"_h, + "uqadd_z_zi"_h, + "uqsub_z_zi"_h}}, + {"'Zd.'[sz], 'Zd.'[sz], 'Zn.'[sz], #'(10?27:9)0", + {"cadd_z_zz"_h, "sqcadd_z_zz"_h}}, + {"'Zd.'[sz], 'Zd.'[sz], 'Zn.'[sz], #'u1816", {"ftmad_z_zzi"_h}}, + {"'Zd.'[sz], 'Zn.'[sz]", + {"frecpe_z_z"_h, "frsqrte_z_z"_h, "rev_z_z"_h, "fexpa_z_z"_h}}, + {"'Zd.'[sz], 'Zn.'[sz], 'Zm.'[sz]", + {"bdep_z_zz"_h, "bext_z_zz"_h, "bgrp_z_zz"_h, + "eorbt_z_zz"_h, "eortb_z_zz"_h, "mul_z_zz"_h, + "smulh_z_zz"_h, "sqdmulh_z_zz"_h, "sqrdmulh_z_zz"_h, + "tbx_z_zz"_h, "umulh_z_zz"_h, "saba_z_zzz"_h, + "sqrdmlah_z_zzz"_h, "sqrdmlsh_z_zzz"_h, "uaba_z_zzz"_h, + "fmmla_z_zzz_s"_h, "fmmla_z_zzz_d"_h, "trn1_z_zz"_h, + "trn2_z_zz"_h, "uzp1_z_zz"_h, "uzp2_z_zz"_h, + "zip1_z_zz"_h, "zip2_z_zz"_h, "add_z_zz"_h, + "sqadd_z_zz"_h, "sqsub_z_zz"_h, "sub_z_zz"_h, + "uqadd_z_zz"_h, "uqsub_z_zz"_h, "fadd_z_zz"_h, + "fmul_z_zz"_h, "frecps_z_zz"_h, "frsqrts_z_zz"_h, + "fsub_z_zz"_h, "ftsmul_z_zz"_h, "ftssel_z_zz"_h}}, + {"'Zd.'[sz], 'Zn.'[sz], 'Zm.'[sz], #'", + {"cmla_z_zzz"_h, "sqrdcmlah_z_zzz"_h}}, + {"'Zd.'[sz], 'Zn.'[sz], 'Zm.d", + {"asr_z_zw"_h, "lsl_z_zw"_h, "lsr_z_zw"_h}}, + {"'Zd.'[sz], 'Zn.'[sszq], 'Zm.'[sszq]", {"sdot_z_zzz"_h, "udot_z_zzz"_h}}, + {"'Zd.'[sz], 'Zn.'[sszq], 'Zm.'[sszq], #'", {"cdot_z_zzz"_h}}, + {"'Zd.'[sz], ['Zn.'[sz], 'Zm.'[sz]'(1110?, lsl #'u1110)]", + {"adr_z_az_sd_same_scaled"_h}}, + {"'Zd.'[sz], {'Zn.'[sz], 'Zn2.'[sz]}, 'Zm.'[sz]", {"tbl_z_zz_2"_h}}, + {"'Zd.'[sz], {'Zn.'[sz]}, 'Zm.'[sz]", {"tbl_z_zz_1"_h}}, + {"'Zd.'[sz], p'u1310, 'Zn.'[sz], 'Zm.'[sz]", {"sel_z_p_zz"_h}}, + {"'Zd.'[sz], p'u1310/m, 'Zn.'[sz]", {"mov_sel_z_p_zz"_h}}, + {"'Zd.'[sszdup], '[sszdup]'u0905", {"mov_1_dup_z_zi"_h}}, + {"'Zd.'[sszdup], 'Zn.'[sszdup][']", + {"mov_dup_z_zi"_h}}, + {"'Zd.'[flogbsz], 'Pgl/m, 'Zn.'[flogbsz]", {"flogb_z_p_z"_h}}, + {"'Zd.'[sszh], 'Zn.'[sz], 'Zm.'[sz]", + {"addhnb_z_zz"_h, + "addhnt_z_zz"_h, + "raddhnb_z_zz"_h, + "raddhnt_z_zz"_h, + "rsubhnb_z_zz"_h, + "rsubhnt_z_zz"_h, + "subhnb_z_zz"_h, + "subhnt_z_zz"_h}}, + {"'Zd.'(17?d:'[sszlog]), 'Zd.'(17?d:'[sszlog]), 'ITriSvel", + {"and_z_zi"_h, "eor_z_zi"_h, "orr_z_zi"_h}}, + {"'Zd.'[sszshd], 'Zn.'[sszshs], #'", + {"sshllb_z_zi"_h, "sshllt_z_zi"_h, "ushllb_z_zi"_h, "ushllt_z_zi"_h}}, + {"'Zd.'[sszshu], 'Pgl/m, 'Zd.'[sszshu], #'", + {"lsl_z_p_zi"_h, "sqshl_z_p_zi"_h, "sqshlu_z_p_zi"_h, "uqshl_z_p_zi"_h}}, + {"'Zd.'[sszshu], 'Pgl/m, 'Zd.'[sszshu], #'<1 35 u2322_0908 clz32 - lsl " + "u2322_0905 ->", + {"asrd_z_p_zi"_h, + "asr_z_p_zi"_h, + "lsr_z_p_zi"_h, + "srshr_z_p_zi"_h, + "urshr_z_p_zi"_h}}, + {"'Zd.'[sszshs], 'Zn.'[sszshd]", + {"sqxtnb_z_zz"_h, + "sqxtnt_z_zz"_h, + "sqxtunb_z_zz"_h, + "sqxtunt_z_zz"_h, + "uqxtnb_z_zz"_h, + "uqxtnt_z_zz"_h}}, + {"'Zd.'[sszshs], 'Zn.'[sszshd], #'<1 35 u2322_2019 clz32 - lsl " + "u2322_2016 ->", + {"rshrnb_z_zi"_h, + "rshrnt_z_zi"_h, + "shrnb_z_zi"_h, + "shrnt_z_zi"_h, + "sqrshrnb_z_zi"_h, + "sqrshrnt_z_zi"_h, + "sqrshrunb_z_zi"_h, + "sqrshrunt_z_zi"_h, + "sqshrnb_z_zi"_h, + "sqshrnt_z_zi"_h, + "sqshrunb_z_zi"_h, + "sqshrunt_z_zi"_h, + "uqrshrnb_z_zi"_h, + "uqrshrnt_z_zi"_h, + "uqshrnb_z_zi"_h, + "uqshrnt_z_zi"_h}}, + {"'Zd.'[sszshs], 'Zn.'[sszshs], #'", + {"lsl_z_zi"_h, "sli_z_zzi"_h}}, + {"'Zd.'[sszshs], 'Zn.'[sszshs], #'<1 35 u2322_2019 clz32 - lsl " + "u2322_2016 ->", + {"asr_z_zi"_h, + "lsr_z_zi"_h, + "sri_z_zzi"_h, + "srsra_z_zi"_h, + "ssra_z_zi"_h, + "ursra_z_zi"_h, + "usra_z_zi"_h}}, + {"'Zd.'[sszshs], 'Zd.'[sszshs], 'Zn.'[sszshs], #'<1 35 u2322_2019 clz32 " + "- lsl u2322_2016 ->", + {"xar_z_zzi"_h}}, + {"'Zd.b, 'Zd.b", {"aesimc_z_z"_h, "aesmc_z_z"_h}}, + {"'Zd.b, 'Zd.b, 'Zn.b", {"aesd_z_zz"_h, "aese_z_zz"_h}}, + {"'Zd.b, 'Zd.b, 'Zn.b, #'u2016_1210", {"ext_z_zi_des"_h}}, + {"'Zd.b, 'Zn.b, 'Zm.b", {"histseg_z_zz"_h, "pmul_z_zz"_h}}, + {"'Zd.b, {'Zn.b, 'Zn2.b}, #'u2016_1210", {"ext_z_zi_con"_h}}, + {"'Zd.d, 'Pgl/m, 'Zn.d", + {"fcvtzs_z_p_z_d2x"_h, + "fcvtzu_z_p_z_d2x"_h, + "scvtf_z_p_z_x2d"_h, + "ucvtf_z_p_z_x2d"_h}}, + {"'Zd.d, 'Pgl/m, 'Zn.h", + {"fcvt_z_p_z_h2d"_h, "fcvtzs_z_p_z_fp162x"_h, "fcvtzu_z_p_z_fp162x"_h}}, + {"'Zd.d, 'Pgl/m, 'Zn.s", + {"fcvt_z_p_z_s2d"_h, + "fcvtlt_z_p_z_s2d"_h, + "fcvtzs_z_p_z_s2x"_h, + "fcvtzu_z_p_z_s2x"_h, + "scvtf_z_p_z_w2d"_h, + "ucvtf_z_p_z_w2d"_h}}, + {"'Zd.d, 'Zd.d, 'Zm.d, 'Zn.d", + {"bcax_z_zzz"_h, + "bsl1n_z_zzz"_h, + "bsl2n_z_zzz"_h, + "bsl_z_zzz"_h, + "eor3_z_zzz"_h, + "nbsl_z_zzz"_h}}, + {"'Zd.d, 'Zn.d", {"mov_orr_z_zz"_h}}, + {"'Zd.d, 'Zn.d, 'Zm.d", + {"rax1_z_zz"_h, "and_z_zz"_h, "bic_z_zz"_h, "eor_z_zz"_h, "orr_z_zz"_h}}, + {"'Zd.d, 'Zn.d, z'u1916.d['u20]", + {"fmla_z_zzzi_d"_h, + "fmls_z_zzzi_d"_h, + "fmul_z_zzi_d"_h, + "mla_z_zzzi_d"_h, + "mls_z_zzzi_d"_h, + "mul_z_zzi_d"_h, + "sqdmulh_z_zzi_d"_h, + "sqrdmulh_z_zzi_d"_h, + "sqrdmlah_z_zzzi_d"_h, + "sqrdmlsh_z_zzzi_d"_h}}, + {"'Zd.d, 'Zn.h, z'u1916.h['u20]", {"sdot_z_zzzi_d"_h, "udot_z_zzzi_d"_h}}, + {"'Zd.d, 'Zn.h, z'u1916.h['u20], #'", {"cdot_z_zzzi_d"_h}}, + {"'Zd.d, 'Zn.s, z'u1916.s['u20_11]", + {"smlalb_z_zzzi_d"_h, + "smlalt_z_zzzi_d"_h, + "smlslb_z_zzzi_d"_h, + "smlslt_z_zzzi_d"_h, + "smullb_z_zzi_d"_h, + "smullt_z_zzi_d"_h, + "sqdmullb_z_zzi_d"_h, + "sqdmullt_z_zzi_d"_h, + "sqdmlalb_z_zzzi_d"_h, + "sqdmlalt_z_zzzi_d"_h, + "sqdmlslb_z_zzzi_d"_h, + "sqdmlslt_z_zzzi_d"_h, + "umlalb_z_zzzi_d"_h, + "umlalt_z_zzzi_d"_h, + "umlslb_z_zzzi_d"_h, + "umlslt_z_zzzi_d"_h, + "umullb_z_zzi_d"_h, + "umullt_z_zzi_d"_h}}, + {"'Zd.d, ['Zn.d, 'Zm.d, sxtw'(1110? #'u1110)]", + {"adr_z_az_d_s32_scaled"_h}}, + {"'Zd.d, ['Zn.d, 'Zm.d, uxtw'(1110? #'u1110)]", + {"adr_z_az_d_u32_scaled"_h}}, + {"'Zd.h, 'Pgl/m, 'Zn.d", + {"fcvt_z_p_z_d2h"_h, "scvtf_z_p_z_x2fp16"_h, "ucvtf_z_p_z_x2fp16"_h}}, + {"'Zd.h, 'Pgl/m, 'Zn.h", + {"fcvtzs_z_p_z_fp162h"_h, + "fcvtzu_z_p_z_fp162h"_h, + "scvtf_z_p_z_h2fp16"_h, + "ucvtf_z_p_z_h2fp16"_h}}, + {"'Zd.h, 'Pgl/m, 'Zn.s", + {"fcvt_z_p_z_s2h"_h, + "fcvtnt_z_p_z_s2h"_h, + "bfcvt_z_p_z_s2bf"_h, + "bfcvtnt_z_p_z_s2bf"_h, + "scvtf_z_p_z_w2fp16"_h, + "ucvtf_z_p_z_w2fp16"_h}}, + {"'Zd.h, 'Zn.h, z'u1816.h['u2019], #'", + {"cmla_z_zzzi_h"_h, "fcmla_z_zzzi_h"_h, "sqrdcmlah_z_zzzi_h"_h}}, + {"'Zd.h, 'Zn.h, z'u1816.h['u22_2019]", + {"fmla_z_zzzi_h"_h, + "fmls_z_zzzi_h"_h, + "fmul_z_zzi_h"_h, + "mla_z_zzzi_h"_h, + "mls_z_zzzi_h"_h, + "mul_z_zzi_h"_h, + "sqdmulh_z_zzi_h"_h, + "sqrdmulh_z_zzi_h"_h, + "sqrdmlah_z_zzzi_h"_h, + "sqrdmlsh_z_zzzi_h"_h}}, + {"'Zd.q, 'Zn.d, 'Zm.d", {"pmullb_z_zz_q"_h, "pmullt_z_zz_q"_h}}, + {"'Zd.s, 'Pgl/m, 'Zn.d", + {"fcvt_z_p_z_d2s"_h, + "fcvtnt_z_p_z_d2s"_h, + "fcvtx_z_p_z_d2s"_h, + "fcvtxnt_z_p_z_d2s"_h, + "fcvtzs_z_p_z_d2w"_h, + "fcvtzu_z_p_z_d2w"_h, + "scvtf_z_p_z_x2s"_h, + "ucvtf_z_p_z_x2s"_h}}, + {"'Zd.s, 'Pgl/m, 'Zn.h", + {"fcvt_z_p_z_h2s"_h, + "fcvtlt_z_p_z_h2s"_h, + "fcvtzs_z_p_z_fp162w"_h, + "fcvtzu_z_p_z_fp162w"_h}}, + {"'Zd.s, 'Pgl/m, 'Zn.s", + {"fcvtzs_z_p_z_s2w"_h, + "fcvtzu_z_p_z_s2w"_h, + "urecpe_z_p_z"_h, + "ursqrte_z_p_z"_h, + "scvtf_z_p_z_w2s"_h, + "ucvtf_z_p_z_w2s"_h}}, + {"'Zd.s, 'Zd.s, 'Zn.s", {"sm4e_z_zz"_h}}, + {"'Zd.s, 'Zn.b, 'Zm.b", + {"smmla_z_zzz"_h, "ummla_z_zzz"_h, "usmmla_z_zzz"_h, "usdot_z_zzz_s"_h}}, + {"'Zd.s, 'Zn.b, z'u1816.b['u2019]", + {"sdot_z_zzzi_s"_h, + "sudot_z_zzzi_s"_h, + "udot_z_zzzi_s"_h, + "usdot_z_zzzi_s"_h}}, + {"'Zd.s, 'Zn.b, z'u1816.b['u2019], #'", {"cdot_z_zzzi_s"_h}}, + {"'Zd.s, 'Zn.h, 'Zm.h", + {"fmlalb_z_zzz"_h, + "fmlalt_z_zzz"_h, + "fmlslb_z_zzz"_h, + "fmlslt_z_zzz"_h, + "bfdot_z_zzz"_h, + "bfmlalb_z_zzz"_h, + "bfmlalt_z_zzz"_h, + "bfmmla_z_zzz"_h}}, + {"'Zd.s, 'Zn.h, z'u1816.h['u2019_11]", + {"fmlalb_z_zzzi_s"_h, "fmlalt_z_zzzi_s"_h, "fmlslb_z_zzzi_s"_h, + "fmlslt_z_zzzi_s"_h, "sqdmlalb_z_zzzi_s"_h, "sqdmlalt_z_zzzi_s"_h, + "sqdmlslb_z_zzzi_s"_h, "sqdmlslt_z_zzzi_s"_h, "bfmlalb_z_zzzi"_h, + "bfmlalt_z_zzzi"_h, "smlalb_z_zzzi_s"_h, "smlalt_z_zzzi_s"_h, + "smlslb_z_zzzi_s"_h, "smlslt_z_zzzi_s"_h, "smullb_z_zzi_s"_h, + "smullt_z_zzi_s"_h, "sqdmullb_z_zzi_s"_h, "sqdmullt_z_zzi_s"_h, + "umlalb_z_zzzi_s"_h, "umlalt_z_zzzi_s"_h, "umlslb_z_zzzi_s"_h, + "umlslt_z_zzzi_s"_h, "umullb_z_zzi_s"_h, "umullt_z_zzi_s"_h}}, + {"'Zd.s, 'Zn.h, z'u1816.h['u2019]", {"bfdot_z_zzzi"_h}}, + {"'Zd.s, 'Zn.s, 'Zm.s", {"sm4ekey_z_zz"_h}}, + {"'Zd.s, 'Zn.s, z'u1816.s['u2019]", + {"fmla_z_zzzi_s"_h, + "fmls_z_zzzi_s"_h, + "fmul_z_zzi_s"_h, + "mla_z_zzzi_s"_h, + "mls_z_zzzi_s"_h, + "mul_z_zzi_s"_h, + "sqdmulh_z_zzi_s"_h, + "sqrdmulh_z_zzi_s"_h, + "sqrdmlah_z_zzzi_s"_h, + "sqrdmlsh_z_zzzi_s"_h}}, + {"'Zd.s, 'Zn.s, z'u1916.s['u20], #'", + {"cmla_z_zzzi_s"_h, "fcmla_z_zzzi_s"_h, "sqrdcmlah_z_zzzi_s"_h}}, + {"'[prefop], pc'(23?:+)' 'LValue", {"prfm_p_loadlit"_h}}, + {"'[prefop], ['Xns'(2012?, #'s2012)]", {"prfum_p_ldst_unscaled"_h}}, + {"'[prefop], ['Xns'(2110?, #')]", {"prfm_p_ldst_pos"_h}}, + {"'[prefop], ['Xns, 'R13m'(1512=6?]'$), '[extmem]'(12? #3)]", + {"prfm_p_ldst_regoff"_h}}, + {"'[prefsveop], 'Pgl, ['Xns'(2116?, #'s2116, mul vl)]", + {"prfb_i_p_bi_s"_h, + "prfd_i_p_bi_s"_h, + "prfh_i_p_bi_s"_h, + "prfw_i_p_bi_s"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Rm'(2423?, lsl #'u2423)]", + {"prfb_i_p_br_s"_h, + "prfd_i_p_br_s"_h, + "prfh_i_p_br_s"_h, + "prfw_i_p_br_s"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.d'(1413?, lsl #'u1413)]", + {"prfb_i_p_bz_d_64_scaled"_h, + "prfd_i_p_bz_d_64_scaled"_h, + "prfh_i_p_bz_d_64_scaled"_h, + "prfw_i_p_bz_d_64_scaled"_h}}, + {"'[prefsveop], 'Pgl, ['Zn.d'(2016?, #'u2016)]", + {"prfb_i_p_ai_d"_h, + "prfd_i_p_ai_d"_h, + "prfh_i_p_ai_d"_h, + "prfw_i_p_ai_d"_h}}, + {"'[prefsveop], 'Pgl, ['Zn.s'(2016?, #'u2016)]", + {"prfb_i_p_ai_s"_h, + "prfd_i_p_ai_s"_h, + "prfh_i_p_ai_s"_h, + "prfw_i_p_ai_s"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.d, '?22:suxtw'(2423? #'u2423)]", + {"prfb_i_p_bz_d_x32_scaled"_h, + "prfd_i_p_bz_d_x32_scaled"_h, + "prfh_i_p_bz_d_x32_scaled"_h, + "prfw_i_p_bz_d_x32_scaled"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.s, '?22:suxtw #1]", + {"prfh_i_p_bz_s_x32_scaled"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.s, '?22:suxtw #2]", + {"prfw_i_p_bz_s_x32_scaled"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.s, '?22:suxtw #3]", + {"prfd_i_p_bz_s_x32_scaled"_h}}, + {"'[prefsveop], 'Pgl, ['Xns, 'Zm.s, '?22:suxtw]", + {"prfb_i_p_bz_s_x32_scaled"_h}}, + {"'[sz]'u0400, 'Pgl, 'Zn.'[sz]", + {"lasta_v_p_z"_h, + "lastb_v_p_z"_h, + "faddv_v_p_z"_h, + "fmaxnmv_v_p_z"_h, + "fmaxv_v_p_z"_h, + "fminnmv_v_p_z"_h, + "fminv_v_p_z"_h}}, + {"'[sz]'u0400, 'Pgl, '[sz]'u0400, 'Zn.'[sz]", + {"clasta_v_p_z"_h, "clastb_v_p_z"_h, "fadda_v_p_z"_h}}, + {"p'u1310, 'Pn.b", {"ptest_p_p"_h}}, + {"{#0x'x2005}", + {"dcps1_dc_exception"_h, + "dcps2_dc_exception"_h, + "dcps3_dc_exception"_h}}, + {"{'Vt.'[nload]}, ['Xns]'(23?, 'Xmr1)", + {"ld1_asisdlse_r1_1v"_h, + "ld1_asisdlsep_i1_i1"_h, + "ld1_asisdlsep_r1_r1"_h, + "st1_asisdlse_r1_1v"_h, + "st1_asisdlsep_i1_i1"_h, + "st1_asisdlsep_r1_r1"_h}}, + {"{'Vt.'[nload]}, ['Xns]'(23?, 'Xmz1)", + {"ld1r_asisdlsop_r1_i"_h, + "ld1r_asisdlsop_rx1_r"_h, + "ld1r_asisdlso_r1"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload]}, ['Xns]'(23?, 'Xmr2)", + {"ld2_asisdlse_r2"_h, + "ld2_asisdlsep_i2_i"_h, + "ld2_asisdlsep_r2_r"_h, + "st2_asisdlse_r2"_h, + "st2_asisdlsep_i2_i"_h, + "st2_asisdlsep_r2_r"_h, + "ld1_asisdlse_r2_2v"_h, + "ld1_asisdlsep_i2_i2"_h, + "ld1_asisdlsep_r2_r2"_h, + "st1_asisdlse_r2_2v"_h, + "st1_asisdlsep_i2_i2"_h, + "st1_asisdlsep_r2_r2"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload]}, ['Xns]'(23?, 'Xmz2)", + {"ld2r_asisdlsop_r2_i"_h, + "ld2r_asisdlsop_rx2_r"_h, + "ld2r_asisdlso_r2"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload], 'Vt3.'[nload]}, ['Xns]'(23?, 'Xmr3)", + {"ld3_asisdlse_r3"_h, + "ld3_asisdlsep_i3_i"_h, + "ld3_asisdlsep_r3_r"_h, + "st3_asisdlse_r3"_h, + "st3_asisdlsep_i3_i"_h, + "st3_asisdlsep_r3_r"_h, + "ld1_asisdlse_r3_3v"_h, + "ld1_asisdlsep_i3_i3"_h, + "ld1_asisdlsep_r3_r3"_h, + "st1_asisdlse_r3_3v"_h, + "st1_asisdlsep_i3_i3"_h, + "st1_asisdlsep_r3_r3"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload], 'Vt3.'[nload]}, ['Xns]'(23?, 'Xmz3)", + {"ld3r_asisdlsop_r3_i"_h, + "ld3r_asisdlsop_rx3_r"_h, + "ld3r_asisdlso_r3"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload], 'Vt3.'[nload], 'Vt4.'[nload]}, " + "['Xns]'(23?, 'Xmr4)", + {"ld4_asisdlse_r4"_h, + "ld4_asisdlsep_i4_i"_h, + "ld4_asisdlsep_r4_r"_h, + "st4_asisdlse_r4"_h, + "st4_asisdlsep_i4_i"_h, + "st4_asisdlsep_r4_r"_h, + "ld1_asisdlse_r4_4v"_h, + "ld1_asisdlsep_i4_i4"_h, + "ld1_asisdlsep_r4_r4"_h, + "st1_asisdlse_r4_4v"_h, + "st1_asisdlsep_i4_i4"_h, + "st1_asisdlsep_r4_r4"_h}}, + {"{'Vt.'[nload], 'Vt2.'[nload], 'Vt3.'[nload], 'Vt4.'[nload]}, " + "['Xns]'(23?, 'Xmz4)", + {"ld4r_asisdlsop_r4_i"_h, + "ld4r_asisdlsop_rx4_r"_h, + "ld4r_asisdlso_r4"_h}}, + {"{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['u30_1210], ['Xns]'(23?, 'Xmb4)", + {"ld4_asisdlsop_b4_i4b"_h, + "ld4_asisdlsop_bx4_r4b"_h, + "st4_asisdlsop_b4_i4b"_h, + "st4_asisdlsop_bx4_r4b"_h, + "ld4_asisdlso_b4_4b"_h, + "st4_asisdlso_b4_4b"_h}}, + {"{'Vt.b, 'Vt2.b, 'Vt3.b}['u30_1210], ['Xns]'(23?, 'Xmb3)", + {"ld3_asisdlsop_b3_i3b"_h, + "ld3_asisdlsop_bx3_r3b"_h, + "st3_asisdlsop_b3_i3b"_h, + "st3_asisdlsop_bx3_r3b"_h, + "ld3_asisdlso_b3_3b"_h, + "st3_asisdlso_b3_3b"_h}}, + {"{'Vt.b, 'Vt2.b}['u30_1210], ['Xns]'(23?, 'Xmb2)", + {"ld2_asisdlsop_b2_i2b"_h, + "ld2_asisdlsop_bx2_r2b"_h, + "st2_asisdlsop_b2_i2b"_h, + "st2_asisdlsop_bx2_r2b"_h, + "ld2_asisdlso_b2_2b"_h, + "st2_asisdlso_b2_2b"_h}}, + {"{'Vt.b}['u30_1210], ['Xns]'(23?, 'Xmb1)", + {"ld1_asisdlsop_b1_i1b"_h, + "ld1_asisdlsop_bx1_r1b"_h, + "st1_asisdlsop_b1_i1b"_h, + "st1_asisdlsop_bx1_r1b"_h, + "ld1_asisdlso_b1_1b"_h, + "st1_asisdlso_b1_1b"_h}}, + {"{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['u30], ['Xns]'(23?, 'Xmb32)", + {"ld4_asisdlsop_d4_i4d"_h, + "ld4_asisdlsop_dx4_r4d"_h, + "st4_asisdlsop_d4_i4d"_h, + "st4_asisdlsop_dx4_r4d"_h, + "ld4_asisdlso_d4_4d"_h, + "st4_asisdlso_d4_4d"_h}}, + {"{'Vt.d, 'Vt2.d, 'Vt3.d}['u30], ['Xns]'(23?, 'Xmb24)", + {"ld3_asisdlsop_d3_i3d"_h, + "ld3_asisdlsop_dx3_r3d"_h, + "st3_asisdlsop_d3_i3d"_h, + "st3_asisdlsop_dx3_r3d"_h, + "ld3_asisdlso_d3_3d"_h, + "st3_asisdlso_d3_3d"_h}}, + {"{'Vt.d, 'Vt2.d}['u30], ['Xns]'(23?, 'Xmb16)", + {"ld2_asisdlsop_d2_i2d"_h, + "ld2_asisdlsop_dx2_r2d"_h, + "st2_asisdlsop_d2_i2d"_h, + "st2_asisdlsop_dx2_r2d"_h, + "ld2_asisdlso_d2_2d"_h, + "st2_asisdlso_d2_2d"_h}}, + {"{'Vt.d}['u30], ['Xns]'(23?, 'Xmb8)", + {"ld1_asisdlsop_d1_i1d"_h, + "ld1_asisdlsop_dx1_r1d"_h, + "st1_asisdlsop_d1_i1d"_h, + "st1_asisdlsop_dx1_r1d"_h, + "ld1_asisdlso_d1_1d"_h, + "st1_asisdlso_d1_1d"_h}}, + {"{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['u30_1211], ['Xns]'(23?, 'Xmb8)", + {"ld4_asisdlso_h4_4h"_h, + "ld4_asisdlsop_h4_i4h"_h, + "ld4_asisdlsop_hx4_r4h"_h, + "st4_asisdlso_h4_4h"_h, + "st4_asisdlsop_h4_i4h"_h, + "st4_asisdlsop_hx4_r4h"_h}}, + {"{'Vt.h, 'Vt2.h, 'Vt3.h}['u30_1211], ['Xns]'(23?, 'Xmb6)", + {"ld3_asisdlso_h3_3h"_h, + "ld3_asisdlsop_h3_i3h"_h, + "ld3_asisdlsop_hx3_r3h"_h, + "st3_asisdlso_h3_3h"_h, + "st3_asisdlsop_h3_i3h"_h, + "st3_asisdlsop_hx3_r3h"_h}}, + {"{'Vt.h, 'Vt2.h}['u30_1211], ['Xns]'(23?, 'Xmb4)", + {"ld2_asisdlso_h2_2h"_h, + "ld2_asisdlsop_h2_i2h"_h, + "ld2_asisdlsop_hx2_r2h"_h, + "st2_asisdlso_h2_2h"_h, + "st2_asisdlsop_h2_i2h"_h, + "st2_asisdlsop_hx2_r2h"_h}}, + {"{'Vt.h}['u30_1211], ['Xns]'(23?, 'Xmb2)", + {"ld1_asisdlso_h1_1h"_h, + "ld1_asisdlsop_h1_i1h"_h, + "ld1_asisdlsop_hx1_r1h"_h, + "st1_asisdlso_h1_1h"_h, + "st1_asisdlsop_h1_i1h"_h, + "st1_asisdlsop_hx1_r1h"_h}}, + {"{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['u30_12], ['Xns]'(23?, 'Xmb16)", + {"ld4_asisdlsop_s4_i4s"_h, + "ld4_asisdlsop_sx4_r4s"_h, + "st4_asisdlsop_s4_i4s"_h, + "st4_asisdlsop_sx4_r4s"_h, + "ld4_asisdlso_s4_4s"_h, + "st4_asisdlso_s4_4s"_h}}, + {"{'Vt.s, 'Vt2.s, 'Vt3.s}['u30_12], ['Xns]'(23?, 'Xmb12)", + {"ld3_asisdlsop_s3_i3s"_h, + "ld3_asisdlsop_sx3_r3s"_h, + "st3_asisdlsop_s3_i3s"_h, + "st3_asisdlsop_sx3_r3s"_h, + "ld3_asisdlso_s3_3s"_h, + "st3_asisdlso_s3_3s"_h}}, + {"{'Vt.s, 'Vt2.s}['u30_12], ['Xns]'(23?, 'Xmb8)", + {"ld2_asisdlsop_s2_i2s"_h, + "ld2_asisdlsop_sx2_r2s"_h, + "st2_asisdlsop_s2_i2s"_h, + "st2_asisdlsop_sx2_r2s"_h, + "ld2_asisdlso_s2_2s"_h, + "st2_asisdlso_s2_2s"_h}}, + {"{'Vt.s}['u30_12], ['Xns]'(23?, 'Xmb4)", + {"ld1_asisdlsop_s1_i1s"_h, + "ld1_asisdlsop_sx1_r1s"_h, + "st1_asisdlsop_s1_i1s"_h, + "st1_asisdlsop_sx1_r1s"_h, + "ld1_asisdlso_s1_1s"_h, + "st1_asisdlso_s1_1s"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns'(1916?, #'s1916, mul vl)]", + {"ld1b_z_p_bi_u16"_h, "ld1b_z_p_bi_u32"_h, "ld1b_z_p_bi_u64"_h, + "ld1b_z_p_bi_u8"_h, "ld1d_z_p_bi_u64"_h, "ld1h_z_p_bi_u16"_h, + "ld1h_z_p_bi_u32"_h, "ld1h_z_p_bi_u64"_h, "ld1sb_z_p_bi_s16"_h, + "ld1sb_z_p_bi_s32"_h, "ld1sb_z_p_bi_s64"_h, "ld1sh_z_p_bi_s32"_h, + "ld1sh_z_p_bi_s64"_h, "ld1sw_z_p_bi_s64"_h, "ld1w_z_p_bi_u32"_h, + "ld1w_z_p_bi_u64"_h, "ldnf1b_z_p_bi_u16"_h, "ldnf1b_z_p_bi_u32"_h, + "ldnf1b_z_p_bi_u64"_h, "ldnf1b_z_p_bi_u8"_h, "ldnf1d_z_p_bi_u64"_h, + "ldnf1h_z_p_bi_u16"_h, "ldnf1h_z_p_bi_u32"_h, "ldnf1h_z_p_bi_u64"_h, + "ldnf1sb_z_p_bi_s16"_h, "ldnf1sb_z_p_bi_s32"_h, "ldnf1sb_z_p_bi_s64"_h, + "ldnf1sh_z_p_bi_s32"_h, "ldnf1sh_z_p_bi_s64"_h, "ldnf1sw_z_p_bi_s64"_h, + "ldnf1w_z_p_bi_u32"_h, "ldnf1w_z_p_bi_u64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns'(2016=31?:, 'Xm)]", + {"ldff1b_z_p_br_u16"_h, + "ldff1b_z_p_br_u32"_h, + "ldff1b_z_p_br_u64"_h, + "ldff1b_z_p_br_u8"_h, + "ldff1sb_z_p_br_s16"_h, + "ldff1sb_z_p_br_s32"_h, + "ldff1sb_z_p_br_s64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns'(2016=31?:, 'Xm, lsl #1)]", + {"ldff1h_z_p_br_u16"_h, + "ldff1h_z_p_br_u32"_h, + "ldff1h_z_p_br_u64"_h, + "ldff1sh_z_p_br_s32"_h, + "ldff1sh_z_p_br_s64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns'(2016=31?:, 'Xm, lsl #2)]", + {"ldff1w_z_p_br_u32"_h, "ldff1w_z_p_br_u64"_h, "ldff1sw_z_p_br_s64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns'(2016=31?:, 'Xm, lsl #3)]", + {"ldff1d_z_p_br_u64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns, 'Xm, lsl #'u2423]", + {"ld1d_z_p_br_u64"_h, + "ld1h_z_p_br_u16"_h, + "ld1h_z_p_br_u32"_h, + "ld1h_z_p_br_u64"_h, + "ld1w_z_p_br_u32"_h, + "ld1w_z_p_br_u64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns, 'Xm, lsl #1]", + {"ld1sh_z_p_br_s32"_h, "ld1sh_z_p_br_s64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns, 'Xm, lsl #2]", {"ld1sw_z_p_br_s64"_h}}, + {"{'Zt.'[sszld]}, 'Pgl/z, ['Xns, 'Xm]", + {"ld1b_z_p_br_u16"_h, + "ld1b_z_p_br_u32"_h, + "ld1b_z_p_br_u64"_h, + "ld1b_z_p_br_u8"_h, + "ld1sb_z_p_br_s16"_h, + "ld1sb_z_p_br_s32"_h, + "ld1sb_z_p_br_s64"_h}}, + {"{'Zt.'[sszst]}, 'Pgl, ['Xns'(1916?, #'s1916, mul vl)]", + {"st1b_z_p_bi"_h, "st1d_z_p_bi"_h, "st1h_z_p_bi"_h, "st1w_z_p_bi"_h}}, + {"{'Zt.'[sszst]}, 'Pgl, ['Xns, 'Xm'(2423?, lsl #'u2423)]", + {"st1b_z_p_br"_h, "st1d_z_p_br"_h, "st1h_z_p_br"_h, "st1w_z_p_br"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem], 'Zt3.'[sszmem], 'Zt4.'[sszmem]}, " + "'Pgl'(30?:/z), ['Xns'(1916?, #', mul vl)]", + {"st4b_z_p_bi_contiguous"_h, + "st4d_z_p_bi_contiguous"_h, + "st4h_z_p_bi_contiguous"_h, + "st4w_z_p_bi_contiguous"_h, + "ld4b_z_p_bi_contiguous"_h, + "ld4d_z_p_bi_contiguous"_h, + "ld4h_z_p_bi_contiguous"_h, + "ld4w_z_p_bi_contiguous"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem], 'Zt3.'[sszmem], 'Zt4.'[sszmem]}, " + "'Pgl'(30?:/z), ['Xns, 'Xm'(2423?, lsl #'u2423)]", + {"st4b_z_p_br_contiguous"_h, + "st4d_z_p_br_contiguous"_h, + "st4h_z_p_br_contiguous"_h, + "st4w_z_p_br_contiguous"_h, + "ld4b_z_p_br_contiguous"_h, + "ld4d_z_p_br_contiguous"_h, + "ld4h_z_p_br_contiguous"_h, + "ld4w_z_p_br_contiguous"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem], 'Zt3.'[sszmem]}, 'Pgl'(30?:/z), " + "['Xns'(1916?, #', mul vl)]", + {"st3b_z_p_bi_contiguous"_h, + "st3d_z_p_bi_contiguous"_h, + "st3h_z_p_bi_contiguous"_h, + "st3w_z_p_bi_contiguous"_h, + "ld3b_z_p_bi_contiguous"_h, + "ld3d_z_p_bi_contiguous"_h, + "ld3h_z_p_bi_contiguous"_h, + "ld3w_z_p_bi_contiguous"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem], 'Zt3.'[sszmem]}, 'Pgl'(30?:/z), ['Xns, " + "'Xm'(2423?, lsl #'u2423)]", + {"st3b_z_p_br_contiguous"_h, + "st3d_z_p_br_contiguous"_h, + "st3h_z_p_br_contiguous"_h, + "st3w_z_p_br_contiguous"_h, + "ld3b_z_p_br_contiguous"_h, + "ld3d_z_p_br_contiguous"_h, + "ld3h_z_p_br_contiguous"_h, + "ld3w_z_p_br_contiguous"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem]}, 'Pgl'(30?:/z), ['Xns'(1916?, " + "#', mul vl)]", + {"st2b_z_p_bi_contiguous"_h, + "st2d_z_p_bi_contiguous"_h, + "st2h_z_p_bi_contiguous"_h, + "st2w_z_p_bi_contiguous"_h, + "ld2b_z_p_bi_contiguous"_h, + "ld2d_z_p_bi_contiguous"_h, + "ld2h_z_p_bi_contiguous"_h, + "ld2w_z_p_bi_contiguous"_h}}, + {"{'Zt.'[sszmem], 'Zt2.'[sszmem]}, 'Pgl'(30?:/z), ['Xns, 'Xm'(2423?, lsl " + "#'u2423)]", + {"st2b_z_p_br_contiguous"_h, + "st2d_z_p_br_contiguous"_h, + "st2h_z_p_br_contiguous"_h, + "st2w_z_p_br_contiguous"_h, + "ld2b_z_p_br_contiguous"_h, + "ld2d_z_p_br_contiguous"_h, + "ld2h_z_p_br_contiguous"_h, + "ld2w_z_p_br_contiguous"_h}}, + {"{'Zt.'[sszmem]}, 'Pgl/z, ['Xns'(1916?, #')]", + {"ld1rqb_z_p_bi_u8"_h, + "ld1rqd_z_p_bi_u64"_h, + "ld1rqh_z_p_bi_u16"_h, + "ld1rqw_z_p_bi_u32"_h}}, + {"{'Zt.'[sszmem]}, 'Pgl/z, ['Xns'(1916?, #')]", + {"ld1rob_z_p_bi_u8"_h, + "ld1rod_z_p_bi_u64"_h, + "ld1roh_z_p_bi_u16"_h, + "ld1row_z_p_bi_u32"_h}}, + {"{'Zt.'[sszmem]}, 'Pgl/z, ['Xns, 'Rm, lsl #'u2423]", + {"ld1rqd_z_p_br_contiguous"_h, + "ld1rqh_z_p_br_contiguous"_h, + "ld1rqw_z_p_br_contiguous"_h, + "ld1rod_z_p_br_contiguous"_h, + "ld1roh_z_p_br_contiguous"_h, + "ld1row_z_p_br_contiguous"_h}}, + {"{'Zt.'[sszmem]}, 'Pgl/z, ['Xns, 'Rm]", + {"ld1rqb_z_p_br_contiguous"_h, "ld1rob_z_p_br_contiguous"_h}}, + {"{'Zt.b}, 'Pgl, ['Xns, 'Rm]", {"stnt1b_z_p_br_contiguous"_h}}, + {"{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]", {"ldnt1b_z_p_br_contiguous"_h}}, + {"{'Zt.b}, 'Pgl/z, ['Xns'(2116?, #'u2116)]", {"ld1rb_z_p_bi_u8"_h}}, + {"{'Zt.b}, 'Pgl'(20?:/z), ['Xns'(1916?, #'s1916, mul vl)]", + {"ldnt1b_z_p_bi_contiguous"_h, "stnt1b_z_p_bi_contiguous"_h}}, + {"{'Zt.d}, 'Pgl'(20?:/z), ['Xns'(1916?, #'s1916, mul vl)]", + {"ldnt1d_z_p_bi_contiguous"_h, "stnt1d_z_p_bi_contiguous"_h}}, + {"{'Zt.d}, 'Pgl'(29?:/z), ['Zn.d'(2016=31?:, 'Xm)]", + {"stnt1b_z_p_ar_d_64_unscaled"_h, + "stnt1d_z_p_ar_d_64_unscaled"_h, + "stnt1h_z_p_ar_d_64_unscaled"_h, + "stnt1w_z_p_ar_d_64_unscaled"_h, + "ldnt1b_z_p_ar_d_64_unscaled"_h, + "ldnt1d_z_p_ar_d_64_unscaled"_h, + "ldnt1h_z_p_ar_d_64_unscaled"_h, + "ldnt1sb_z_p_ar_d_64_unscaled"_h, + "ldnt1sh_z_p_ar_d_64_unscaled"_h, + "ldnt1sw_z_p_ar_d_64_unscaled"_h, + "ldnt1w_z_p_ar_d_64_unscaled"_h}}, + {"{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]", {"stnt1d_z_p_br_contiguous"_h}}, + {"{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]", + {"st1d_z_p_bz_d_x32_scaled"_h, + "st1h_z_p_bz_d_x32_scaled"_h, + "st1w_z_p_bz_d_x32_scaled"_h}}, + {"{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]", + {"st1b_z_p_bz_d_x32_unscaled"_h, + "st1d_z_p_bz_d_x32_unscaled"_h, + "st1h_z_p_bz_d_x32_unscaled"_h, + "st1w_z_p_bz_d_x32_unscaled"_h}}, + {"{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]", + {"st1d_z_p_bz_d_64_scaled"_h, + "st1h_z_p_bz_d_64_scaled"_h, + "st1w_z_p_bz_d_64_scaled"_h}}, + {"{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]", + {"st1b_z_p_bz_d_64_unscaled"_h, + "st1d_z_p_bz_d_64_unscaled"_h, + "st1h_z_p_bz_d_64_unscaled"_h, + "st1w_z_p_bz_d_64_unscaled"_h}}, + {"{'Zt.d}, 'Pgl, ['Zn.d'(2016?, #'u2016)]", {"st1b_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl, ['Zn.d'(2016?, #')]", {"st1h_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl, ['Zn.d'(2016?, #')]", {"st1w_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl, ['Zn.d'(2016?, #')]", {"st1d_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns'(2116?, #'u2116)]", + {"ld1rb_z_p_bi_u64"_h, "ld1rsb_z_p_bi_s64"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rh_z_p_bi_u64"_h, "ld1rsh_z_p_bi_s64"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rw_z_p_bi_u64"_h, "ld1rsw_z_p_bi_s64"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rd_z_p_bi_u64"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]", {"ldnt1d_z_p_br_contiguous"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw #'u2423]", + {"ld1d_z_p_bz_d_x32_scaled"_h, + "ld1h_z_p_bz_d_x32_scaled"_h, + "ld1sh_z_p_bz_d_x32_scaled"_h, + "ld1sw_z_p_bz_d_x32_scaled"_h, + "ld1w_z_p_bz_d_x32_scaled"_h, + "ldff1d_z_p_bz_d_x32_scaled"_h, + "ldff1h_z_p_bz_d_x32_scaled"_h, + "ldff1sh_z_p_bz_d_x32_scaled"_h, + "ldff1sw_z_p_bz_d_x32_scaled"_h, + "ldff1w_z_p_bz_d_x32_scaled"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]", + {"ld1b_z_p_bz_d_x32_unscaled"_h, + "ld1d_z_p_bz_d_x32_unscaled"_h, + "ld1h_z_p_bz_d_x32_unscaled"_h, + "ld1sb_z_p_bz_d_x32_unscaled"_h, + "ld1sh_z_p_bz_d_x32_unscaled"_h, + "ld1sw_z_p_bz_d_x32_unscaled"_h, + "ld1w_z_p_bz_d_x32_unscaled"_h, + "ldff1b_z_p_bz_d_x32_unscaled"_h, + "ldff1d_z_p_bz_d_x32_unscaled"_h, + "ldff1h_z_p_bz_d_x32_unscaled"_h, + "ldff1sb_z_p_bz_d_x32_unscaled"_h, + "ldff1sh_z_p_bz_d_x32_unscaled"_h, + "ldff1sw_z_p_bz_d_x32_unscaled"_h, + "ldff1w_z_p_bz_d_x32_unscaled"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]", + {"ld1d_z_p_bz_d_64_scaled"_h, + "ld1h_z_p_bz_d_64_scaled"_h, + "ld1sh_z_p_bz_d_64_scaled"_h, + "ld1sw_z_p_bz_d_64_scaled"_h, + "ld1w_z_p_bz_d_64_scaled"_h, + "ldff1d_z_p_bz_d_64_scaled"_h, + "ldff1h_z_p_bz_d_64_scaled"_h, + "ldff1sh_z_p_bz_d_64_scaled"_h, + "ldff1sw_z_p_bz_d_64_scaled"_h, + "ldff1w_z_p_bz_d_64_scaled"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]", + {"ld1b_z_p_bz_d_64_unscaled"_h, + "ld1d_z_p_bz_d_64_unscaled"_h, + "ld1h_z_p_bz_d_64_unscaled"_h, + "ld1sb_z_p_bz_d_64_unscaled"_h, + "ld1sh_z_p_bz_d_64_unscaled"_h, + "ld1sw_z_p_bz_d_64_unscaled"_h, + "ld1w_z_p_bz_d_64_unscaled"_h, + "ldff1b_z_p_bz_d_64_unscaled"_h, + "ldff1d_z_p_bz_d_64_unscaled"_h, + "ldff1h_z_p_bz_d_64_unscaled"_h, + "ldff1sb_z_p_bz_d_64_unscaled"_h, + "ldff1sh_z_p_bz_d_64_unscaled"_h, + "ldff1sw_z_p_bz_d_64_unscaled"_h, + "ldff1w_z_p_bz_d_64_unscaled"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Zn.d'(2016?, #'u2016)]", + {"ld1b_z_p_ai_d"_h, + "ld1sb_z_p_ai_d"_h, + "ldff1b_z_p_ai_d"_h, + "ldff1sb_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Zn.d'(2016?, #')]", + {"ld1h_z_p_ai_d"_h, + "ld1sh_z_p_ai_d"_h, + "ldff1h_z_p_ai_d"_h, + "ldff1sh_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Zn.d'(2016?, #')]", + {"ld1sw_z_p_ai_d"_h, + "ld1w_z_p_ai_d"_h, + "ldff1sw_z_p_ai_d"_h, + "ldff1w_z_p_ai_d"_h}}, + {"{'Zt.d}, 'Pgl/z, ['Zn.d'(2016?, #')]", + {"ld1d_z_p_ai_d"_h, "ldff1d_z_p_ai_d"_h}}, + {"{'Zt.h}, 'Pgl'(30?:/z), ['Xns, 'Rm, lsl #1]", + {"ldnt1h_z_p_br_contiguous"_h, "stnt1h_z_p_br_contiguous"_h}}, + {"{'Zt.h}, 'Pgl'(20?:/z), ['Xns'(1916?, #'s1916, mul vl)]", + {"ldnt1h_z_p_bi_contiguous"_h, "stnt1h_z_p_bi_contiguous"_h}}, + {"{'Zt.h}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rb_z_p_bi_u16"_h, "ld1rsb_z_p_bi_s16"_h}}, + {"{'Zt.h}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rh_z_p_bi_u16"_h}}, + {"{'Zt.s}, 'Pgl'(29?:/z), ['Zn.s'(2016=31?:, 'Xm)]", + {"stnt1b_z_p_ar_s_x32_unscaled"_h, + "stnt1h_z_p_ar_s_x32_unscaled"_h, + "stnt1w_z_p_ar_s_x32_unscaled"_h, + "ldnt1b_z_p_ar_s_x32_unscaled"_h, + "ldnt1h_z_p_ar_s_x32_unscaled"_h, + "ldnt1sb_z_p_ar_s_x32_unscaled"_h, + "ldnt1sh_z_p_ar_s_x32_unscaled"_h, + "ldnt1w_z_p_ar_s_x32_unscaled"_h}}, + {"{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]", {"stnt1w_z_p_br_contiguous"_h}}, + {"{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]", + {"st1h_z_p_bz_s_x32_scaled"_h, "st1w_z_p_bz_s_x32_scaled"_h}}, + {"{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]", + {"st1b_z_p_bz_s_x32_unscaled"_h, + "st1h_z_p_bz_s_x32_unscaled"_h, + "st1w_z_p_bz_s_x32_unscaled"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns'(2116?, #'u2116)]", + {"ld1rb_z_p_bi_u32"_h, "ld1rsb_z_p_bi_s32"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rh_z_p_bi_u32"_h, "ld1rsh_z_p_bi_s32"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns'(2116?, #')]", + {"ld1rw_z_p_bi_u32"_h, "ld1rsw_z_p_bi_s32"_h}}, + {"{'Zt.s}, 'Pgl'(20?:/z), ['Xns'(1916?, #'s1916, mul vl)]", + {"ldnt1w_z_p_bi_contiguous"_h, "stnt1w_z_p_bi_contiguous"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]", {"ldnt1w_z_p_br_contiguous"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]", + {"ld1h_z_p_bz_s_x32_scaled"_h, + "ld1sh_z_p_bz_s_x32_scaled"_h, + "ldff1h_z_p_bz_s_x32_scaled"_h, + "ldff1sh_z_p_bz_s_x32_scaled"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]", + {"ld1w_z_p_bz_s_x32_scaled"_h, "ldff1w_z_p_bz_s_x32_scaled"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]", + {"ld1b_z_p_bz_s_x32_unscaled"_h, + "ld1h_z_p_bz_s_x32_unscaled"_h, + "ld1sb_z_p_bz_s_x32_unscaled"_h, + "ld1sh_z_p_bz_s_x32_unscaled"_h, + "ld1w_z_p_bz_s_x32_unscaled"_h, + "ldff1b_z_p_bz_s_x32_unscaled"_h, + "ldff1h_z_p_bz_s_x32_unscaled"_h, + "ldff1sb_z_p_bz_s_x32_unscaled"_h, + "ldff1sh_z_p_bz_s_x32_unscaled"_h, + "ldff1w_z_p_bz_s_x32_unscaled"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Zn.s'(2016?, #'u2016)]", + {"ld1b_z_p_ai_s"_h, + "ld1sb_z_p_ai_s"_h, + "ldff1b_z_p_ai_s"_h, + "ldff1sb_z_p_ai_s"_h}}, + {"{'Zt.s}, 'Pgl, ['Zn.s'(2016?, #'u2016)]", {"st1b_z_p_ai_s"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Zn.s'(2016?, #')]", + {"ld1h_z_p_ai_s"_h, + "ld1sh_z_p_ai_s"_h, + "ldff1h_z_p_ai_s"_h, + "ldff1sh_z_p_ai_s"_h}}, + {"{'Zt.s}, 'Pgl, ['Zn.s'(2016?, #')]", {"st1h_z_p_ai_s"_h}}, + {"{'Zt.s}, 'Pgl/z, ['Zn.s'(2016?, #')]", + {"ld1w_z_p_ai_s"_h, "ldff1w_z_p_ai_s"_h}}, + {"{'Zt.s}, 'Pgl, ['Zn.s'(2016?, #')]", {"st1w_z_p_ai_s"_h}}, + {"'Zd.'[sz], 'Pgl/m, 'Zd.'[sz], 'Zn.d", + {"asr_z_p_zw"_h, "lsl_z_p_zw"_h, "lsr_z_p_zw"_h}}, + {"'Zd.'[sz], 'Zn.'[sz], 'Zm.'[sszh]", + {"saddwb_z_zz"_h, + "saddwt_z_zz"_h, + "ssubwb_z_zz"_h, + "ssubwt_z_zz"_h, + "uaddwb_z_zz"_h, + "uaddwt_z_zz"_h, + "usubwb_z_zz"_h, + "usubwt_z_zz"_h}}, + {"'Zd.'[sz], 'Zn.'[sszh]", + {"sunpkhi_z_z"_h, "sunpklo_z_z"_h, "uunpkhi_z_z"_h, "uunpklo_z_z"_h}}, + {"'Zd.'[sz], 'Zn.'[sszh], 'Zm.'[sszh]", + {"smlalb_z_zzz"_h, "smlalt_z_zzz"_h, "smlslb_z_zzz"_h, + "smlslt_z_zzz"_h, "sqdmlalb_z_zzz"_h, "sqdmlalbt_z_zzz"_h, + "sqdmlalt_z_zzz"_h, "sqdmlslb_z_zzz"_h, "sqdmlslbt_z_zzz"_h, + "sqdmlslt_z_zzz"_h, "umlalb_z_zzz"_h, "umlalt_z_zzz"_h, + "umlslb_z_zzz"_h, "umlslt_z_zzz"_h, "sabalb_z_zzz"_h, + "sabalt_z_zzz"_h, "sabdlb_z_zz"_h, "sabdlt_z_zz"_h, + "saddlb_z_zz"_h, "saddlbt_z_zz"_h, "saddlt_z_zz"_h, + "smullb_z_zz"_h, "smullt_z_zz"_h, "sqdmullb_z_zz"_h, + "sqdmullt_z_zz"_h, "ssublb_z_zz"_h, "ssublbt_z_zz"_h, + "ssublt_z_zz"_h, "ssubltb_z_zz"_h, "uabalb_z_zzz"_h, + "uabalt_z_zzz"_h, "uabdlb_z_zz"_h, "uabdlt_z_zz"_h, + "uaddlb_z_zz"_h, "uaddlt_z_zz"_h, "umullb_z_zz"_h, + "umullt_z_zz"_h, "usublb_z_zz"_h, "usublt_z_zz"_h, + "pmullb_z_zz"_h, "pmullt_z_zz"_h}}, + {"'Zt, ['Xns'(2110=16?:, #'s2116_1210, mul vl)]", + {"ldr_z_bi"_h, "str_z_bi"_h}}, + {"ivau, 'Xt", {"ic_sys_cr_systeminstrs"_h}}, + {"'{dcop}, 'Xt", {"dc_sys_cr_systeminstrs"_h}}, + {"'{pstatefield}, #'u1108", {"msr_si_pstate"_h}}, + {"csync", {"psb_c_hints"_h, "tsb_hc_hints"_h}}, + {"x16", {"chkfeat_hf_hints"_h}}}; + + for (auto &itm : forms) { + const std::unordered_set &s = forms.at(itm.first); + for (const uint32_t &its : s) { + fts->insert(std::make_pair(its, itm.first.c_str())); + } + } +} + const Disassembler::FormToVisitorFnMap *Disassembler::GetFormToVisitorFnMap() { static const FormToVisitorFnMap form_to_visitor = { DEFAULT_FORM_TO_VISITOR_MAP(Disassembler), - {"autia1716_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"autiasp_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"autiaz_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"autib1716_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"autibsp_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"autibz_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"axflag_m_pstate"_h, &Disassembler::DisassembleNoArgs}, - {"cfinv_m_pstate"_h, &Disassembler::DisassembleNoArgs}, - {"csdb_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"dgh_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"ssbb_only_barriers"_h, &Disassembler::DisassembleNoArgs}, - {"esb_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"isb_bi_barriers"_h, &Disassembler::DisassembleNoArgs}, - {"nop_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"pacia1716_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"paciasp_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"paciaz_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"pacib1716_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"pacibsp_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"pacibz_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"sev_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"sevl_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"wfe_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"wfi_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"xaflag_m_pstate"_h, &Disassembler::DisassembleNoArgs}, - {"xpaclri_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"yield_hi_hints"_h, &Disassembler::DisassembleNoArgs}, - {"abs_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"cls_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"clz_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"cnt_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"neg_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"rev16_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"rev32_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"rev64_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"sqabs_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"sqneg_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"suqadd_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"urecpe_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"ursqrte_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"usqadd_asimdmisc_r"_h, &Disassembler::VisitNEON2RegMisc}, - {"not_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegLogical}, - {"rbit_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegLogical}, - {"xtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract}, - {"sqxtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract}, - {"uqxtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract}, - {"sqxtun_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegExtract}, - {"shll_asimdmisc_s"_h, &Disassembler::DisassembleNEON2RegExtract}, - {"sadalp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp}, - {"saddlp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp}, - {"uadalp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp}, - {"uaddlp_asimdmisc_p"_h, &Disassembler::DisassembleNEON2RegAddlp}, - {"cmeq_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare}, - {"cmge_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare}, - {"cmgt_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare}, - {"cmle_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare}, - {"cmlt_asimdmisc_z"_h, &Disassembler::DisassembleNEON2RegCompare}, - {"fcmeq_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare}, - {"fcmge_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare}, - {"fcmgt_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare}, - {"fcmle_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare}, - {"fcmlt_asimdmisc_fz"_h, &Disassembler::DisassembleNEON2RegFPCompare}, - {"fcvtl_asimdmisc_l"_h, &Disassembler::DisassembleNEON2RegFPConvert}, - {"fcvtn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegFPConvert}, - {"fcvtxn_asimdmisc_n"_h, &Disassembler::DisassembleNEON2RegFPConvert}, - {"fabs_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtas_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtau_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtms_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtmu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtns_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtnu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtps_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtpu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtzs_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fcvtzu_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fneg_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frecpe_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frint32x_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frint32z_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frint64x_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frint64z_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frinta_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frinti_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frintm_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frintn_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frintp_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frintx_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frintz_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"frsqrte_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"fsqrt_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"scvtf_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"ucvtf_asimdmisc_r"_h, &Disassembler::DisassembleNEON2RegFP}, - {"smlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"smlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"smull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"umlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"umlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"umull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"sqdmull_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"sqdmlal_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"sqdmlsl_asimdelem_l"_h, &Disassembler::DisassembleNEONMulByElementLong}, - {"sdot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement}, - {"udot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement}, - {"usdot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement}, - {"sudot_asimdelem_d"_h, &Disassembler::DisassembleNEONDotProdByElement}, - {"fmlal2_asimdelem_lh"_h, - &Disassembler::DisassembleNEONFPMulByElementLong}, - {"fmlal_asimdelem_lh"_h, - &Disassembler::DisassembleNEONFPMulByElementLong}, - {"fmlsl2_asimdelem_lh"_h, - &Disassembler::DisassembleNEONFPMulByElementLong}, - {"fmlsl_asimdelem_lh"_h, - &Disassembler::DisassembleNEONFPMulByElementLong}, - {"fcmla_asimdelem_c_h"_h, - &Disassembler::DisassembleNEONComplexMulByElement}, - {"fcmla_asimdelem_c_s"_h, - &Disassembler::DisassembleNEONComplexMulByElement}, - {"fmla_asimdelem_rh_h"_h, - &Disassembler::DisassembleNEONHalfFPMulByElement}, - {"fmls_asimdelem_rh_h"_h, - &Disassembler::DisassembleNEONHalfFPMulByElement}, - {"fmulx_asimdelem_rh_h"_h, - &Disassembler::DisassembleNEONHalfFPMulByElement}, - {"fmul_asimdelem_rh_h"_h, - &Disassembler::DisassembleNEONHalfFPMulByElement}, - {"fmla_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement}, - {"fmls_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement}, - {"fmulx_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement}, - {"fmul_asimdelem_r_sd"_h, &Disassembler::DisassembleNEONFPMulByElement}, - {"mla_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"mls_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"mul_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"saba_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"sabd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"shadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"shsub_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"smaxp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"smax_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"sminp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"smin_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"srhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"uaba_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"uabd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"uhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"uhsub_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"umaxp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"umax_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"uminp_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"umin_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"urhadd_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameNoD}, - {"and_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"bic_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"bif_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"bit_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"bsl_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"eor_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"orr_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"orn_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"pmul_asimdsame_only"_h, &Disassembler::DisassembleNEON3SameLogical}, - {"fmlal2_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM}, - {"fmlal_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM}, - {"fmlsl2_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM}, - {"fmlsl_asimdsame_f"_h, &Disassembler::DisassembleNEON3SameFHM}, - {"sri_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"srshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"srsra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"sshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"ssra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"urshr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"ursra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"ushr_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"usra_asimdshf_r"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"scvtf_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"ucvtf_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"fcvtzs_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"fcvtzu_asimdshf_c"_h, &Disassembler::DisassembleNEONShiftRightImm}, - {"ushll_asimdshf_l"_h, &Disassembler::DisassembleNEONShiftLeftLongImm}, - {"sshll_asimdshf_l"_h, &Disassembler::DisassembleNEONShiftLeftLongImm}, - {"shrn_asimdshf_n"_h, &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"rshrn_asimdshf_n"_h, &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"sqshrn_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"sqrshrn_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"sqshrun_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"sqrshrun_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"uqshrn_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"uqrshrn_asimdshf_n"_h, - &Disassembler::DisassembleNEONShiftRightNarrowImm}, - {"sqdmlal_asisdelem_l"_h, - &Disassembler::DisassembleNEONScalarSatMulLongIndex}, - {"sqdmlsl_asisdelem_l"_h, - &Disassembler::DisassembleNEONScalarSatMulLongIndex}, - {"sqdmull_asisdelem_l"_h, - &Disassembler::DisassembleNEONScalarSatMulLongIndex}, - {"fmla_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmla_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmls_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmls_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmulx_asisdelem_rh_h"_h, - &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmulx_asisdelem_r_sd"_h, - &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmul_asisdelem_rh_h"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fmul_asisdelem_r_sd"_h, &Disassembler::DisassembleNEONFPScalarMulIndex}, - {"fabd_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"facge_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"facgt_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"fcmeq_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"fcmge_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"fcmgt_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"fmulx_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"frecps_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"frsqrts_asisdsame_only"_h, &Disassembler::DisassembleNEONFPScalar3Same}, - {"sqrdmlah_asisdsame2_only"_h, &Disassembler::VisitNEONScalar3Same}, - {"sqrdmlsh_asisdsame2_only"_h, &Disassembler::VisitNEONScalar3Same}, - {"cmeq_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"cmge_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"cmgt_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"cmhi_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"cmhs_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"cmtst_asisdsame_only"_h, - &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"add_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"sub_asisdsame_only"_h, &Disassembler::DisassembleNEONScalar3SameOnlyD}, - {"fmaxnmv_asimdall_only_h"_h, - &Disassembler::DisassembleNEONFP16AcrossLanes}, - {"fmaxv_asimdall_only_h"_h, - &Disassembler::DisassembleNEONFP16AcrossLanes}, - {"fminnmv_asimdall_only_h"_h, - &Disassembler::DisassembleNEONFP16AcrossLanes}, - {"fminv_asimdall_only_h"_h, - &Disassembler::DisassembleNEONFP16AcrossLanes}, - {"fmaxnmv_asimdall_only_sd"_h, - &Disassembler::DisassembleNEONFPAcrossLanes}, - {"fminnmv_asimdall_only_sd"_h, - &Disassembler::DisassembleNEONFPAcrossLanes}, - {"fmaxv_asimdall_only_sd"_h, &Disassembler::DisassembleNEONFPAcrossLanes}, - {"fminv_asimdall_only_sd"_h, &Disassembler::DisassembleNEONFPAcrossLanes}, - {"shl_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"sli_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"sri_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"srshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"srsra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"sshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"ssra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"urshr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"ursra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"ushr_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"usra_asisdshf_r"_h, &Disassembler::DisassembleNEONScalarShiftImmOnlyD}, - {"sqrshrn_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"sqrshrun_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"sqshrn_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"sqshrun_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"uqrshrn_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"uqshrn_asisdshf_n"_h, - &Disassembler::DisassembleNEONScalarShiftRightNarrowImm}, - {"cmeq_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"cmge_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"cmgt_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"cmle_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"cmlt_asisdmisc_z"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"abs_asisdmisc_r"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"neg_asisdmisc_r"_h, &Disassembler::DisassembleNEONScalar2RegMiscOnlyD}, - {"fcmeq_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcmge_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcmgt_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcmle_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcmlt_asisdmisc_fz"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtas_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtau_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtms_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtmu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtns_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtnu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtps_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtpu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtxn_asisdmisc_n"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtzs_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"fcvtzu_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"frecpe_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"frecpx_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"frsqrte_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"scvtf_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"ucvtf_asisdmisc_r"_h, &Disassembler::DisassembleNEONFPScalar2RegMisc}, - {"pmull_asimddiff_l"_h, &Disassembler::DisassembleNEONPolynomialMul}, - {"adclb_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry}, - {"adclt_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry}, - {"addhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"addhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"addp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"aesd_z_zz"_h, &Disassembler::Disassemble_ZdnB_ZdnB_ZmB}, - {"aese_z_zz"_h, &Disassembler::Disassemble_ZdnB_ZdnB_ZmB}, - {"aesimc_z_z"_h, &Disassembler::Disassemble_ZdnB_ZdnB}, - {"aesmc_z_z"_h, &Disassembler::Disassemble_ZdnB_ZdnB}, - {"bcax_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"bdep_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"bext_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"bgrp_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"bsl1n_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"bsl2n_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"bsl_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"cadd_z_zz"_h, &Disassembler::DisassembleSVEComplexIntAddition}, - {"cdot_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const}, - {"cdot_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const}, - {"cdot_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const}, - {"cmla_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const}, - {"cmla_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const}, - {"cmla_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const}, - {"eor3_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"eorbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"eortb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"ext_z_zi_con"_h, &Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm}, - {"faddp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair}, - {"fcvtlt_z_p_z_h2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnH}, - {"fcvtlt_z_p_z_s2d"_h, &Disassembler::Disassemble_ZdD_PgM_ZnS}, - {"fcvtnt_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD}, - {"fcvtnt_z_p_z_s2h"_h, &Disassembler::Disassemble_ZdH_PgM_ZnS}, - {"fcvtx_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD}, - {"fcvtxnt_z_p_z_d2s"_h, &Disassembler::Disassemble_ZdS_PgM_ZnD}, - {"flogb_z_p_z"_h, &Disassembler::DisassembleSVEFlogb}, - {"fmaxnmp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair}, - {"fmaxp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair}, - {"fminnmp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair}, - {"fminp_z_p_zz"_h, &Disassembler::DisassembleSVEFPPair}, - {"fmlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH}, - {"fmlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"fmlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH}, - {"fmlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"fmlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH}, - {"fmlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"fmlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH}, - {"fmlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"histcnt_z_p_zz"_h, &Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT}, - {"histseg_z_zz"_h, &Disassembler::Disassemble_ZdB_ZnB_ZmB}, - {"ldnt1b_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1b_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm}, - {"ldnt1d_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1h_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1h_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm}, - {"ldnt1sb_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1sb_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm}, - {"ldnt1sh_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1sh_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm}, - {"ldnt1sw_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1w_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm}, - {"ldnt1w_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm}, - {"match_p_p_zz"_h, &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT}, - {"mla_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm}, - {"mla_z_zzzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm}, - {"mla_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm}, - {"mls_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm}, - {"mls_z_zzzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm}, - {"mls_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm}, - {"mul_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"mul_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm}, - {"mul_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm}, - {"mul_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm}, - {"nbsl_z_zzz"_h, &Disassembler::DisassembleSVEBitwiseTernary}, - {"nmatch_p_p_zz"_h, &Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT}, - {"pmul_z_zz"_h, &Disassembler::Disassemble_ZdB_ZnB_ZmB}, - {"pmullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"pmullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"raddhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"raddhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"rax1_z_zz"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD}, - {"rshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"rshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"rsubhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"rsubhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"saba_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"sabalb_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sabalt_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sabdlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sabdlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sadalp_z_p_z"_h, &Disassembler::Disassemble_ZdaT_PgM_ZnTb}, - {"saddlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"saddlbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"saddlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"saddwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"saddwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"sbclb_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry}, - {"sbclt_z_zzz"_h, &Disassembler::DisassembleSVEAddSubCarry}, - {"shadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"shrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"shrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"shsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"shsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sli_z_zzi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"sm4e_z_zz"_h, &Disassembler::Disassemble_ZdnS_ZdnS_ZmS}, - {"sm4ekey_z_zz"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS}, - {"smaxp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sminp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"smlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"smlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"smlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"smlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"smlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"smlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"smlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"smlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"smulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"smullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"smullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"smullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"smullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"smullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"splice_z_p_zz_con"_h, &Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T}, - {"sqabs_z_p_z"_h, &Disassembler::Disassemble_ZdT_PgM_ZnT}, - {"sqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqcadd_z_zz"_h, &Disassembler::DisassembleSVEComplexIntAddition}, - {"sqdmlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm}, - {"sqdmlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"sqdmlalbt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm}, - {"sqdmlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"sqdmlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm}, - {"sqdmlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"sqdmlslbt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"sqdmlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm}, - {"sqdmlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm}, - {"sqdmulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"sqdmulh_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm}, - {"sqdmulh_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm}, - {"sqdmulh_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm}, - {"sqdmullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sqdmullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"sqdmullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"sqdmullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"sqdmullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"sqdmullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"sqneg_z_p_z"_h, &Disassembler::Disassemble_ZdT_PgM_ZnT}, - {"sqrdcmlah_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT_const}, - {"sqrdcmlah_z_zzzi_h"_h, - &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const}, - {"sqrdcmlah_z_zzzi_s"_h, - &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const}, - {"sqrdmlah_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"sqrdmlah_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm}, - {"sqrdmlah_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm}, - {"sqrdmlah_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm}, - {"sqrdmlsh_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"sqrdmlsh_z_zzzi_d"_h, &Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm}, - {"sqrdmlsh_z_zzzi_h"_h, &Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm}, - {"sqrdmlsh_z_zzzi_s"_h, &Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm}, - {"sqrdmulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"sqrdmulh_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnD_ZmD_imm}, - {"sqrdmulh_z_zzi_h"_h, &Disassembler::Disassemble_ZdH_ZnH_ZmH_imm}, - {"sqrdmulh_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnS_ZmS_imm}, - {"sqrshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqrshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqrshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqrshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqrshrunb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqrshrunt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqshl_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated}, - {"sqshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqshlu_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated}, - {"sqshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqshrunb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqshrunt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"sqsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sqxtnb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"sqxtnt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"sqxtunb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"sqxtunt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"srhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"sri_z_zzi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"srshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"srshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"srshr_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated}, - {"srsra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"sshllb_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm}, - {"sshllt_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm}, - {"ssra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"ssublb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"ssublbt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"ssublt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"ssubltb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"ssubwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"ssubwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"stnt1b_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm}, - {"stnt1b_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm}, - {"stnt1d_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm}, - {"stnt1h_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm}, - {"stnt1h_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm}, - {"stnt1w_z_p_ar_d_64_unscaled"_h, - &Disassembler::Disassemble_ZtD_Pg_ZnD_Xm}, - {"stnt1w_z_p_ar_s_x32_unscaled"_h, - &Disassembler::Disassemble_ZtS_Pg_ZnS_Xm}, - {"subhnb_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"subhnt_z_zz"_h, &Disassembler::DisassembleSVEAddSubHigh}, - {"suqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"tbl_z_zz_2"_h, &Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT}, - {"tbx_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"uaba_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"uabalb_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uabalt_z_zzz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uabdlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uabdlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uadalp_z_p_z"_h, &Disassembler::Disassemble_ZdaT_PgM_ZnTb}, - {"uaddlb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uaddlt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"uaddwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"uaddwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"uhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uhsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uhsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"umaxp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uminp_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"umlalb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"umlalb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umlalb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"umlalt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"umlalt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umlalt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"umlslb_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"umlslb_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umlslb_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"umlslt_z_zzz"_h, &Disassembler::Disassemble_ZdaT_ZnTb_ZmTb}, - {"umlslt_z_zzzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umlslt_z_zzzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"umulh_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmT}, - {"umullb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"umullb_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umullb_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"umullt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"umullt_z_zzi_d"_h, &Disassembler::Disassemble_ZdD_ZnS_ZmS_imm}, - {"umullt_z_zzi_s"_h, &Disassembler::Disassemble_ZdS_ZnH_ZmH_imm}, - {"uqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqrshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqrshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqrshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"uqrshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"uqshl_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated}, - {"uqshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqshrnb_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"uqshrnt_z_zi"_h, &Disassembler::DisassembleSVEShiftRightImm}, - {"uqsub_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqsubr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"uqxtnb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"uqxtnt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb}, - {"urecpe_z_p_z"_h, &Disassembler::Disassemble_ZdS_PgM_ZnS}, - {"urhadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"urshl_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"urshlr_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"urshr_z_p_zi"_h, &Disassembler::VisitSVEBitwiseShiftByImm_Predicated}, - {"ursqrte_z_p_z"_h, &Disassembler::Disassemble_ZdS_PgM_ZnS}, - {"ursra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"ushllb_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm}, - {"ushllt_z_zi"_h, &Disassembler::DisassembleSVEShiftLeftImm}, - {"usqadd_z_p_zz"_h, &Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT}, - {"usra_z_zi"_h, &Disassembler::VisitSVEBitwiseShiftUnpredicated}, - {"usublb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"usublt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnTb_ZmTb}, - {"usubwb_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"usubwt_z_zz"_h, &Disassembler::Disassemble_ZdT_ZnT_ZmTb}, - {"whilege_p_p_rr"_h, - &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"whilegt_p_p_rr"_h, - &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"whilehi_p_p_rr"_h, - &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"whilehs_p_p_rr"_h, - &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"whilerw_p_rr"_h, &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"whilewr_p_rr"_h, &Disassembler::VisitSVEIntCompareScalarCountAndLimit}, - {"xar_z_zzi"_h, &Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const}, - {"fmmla_z_zzz_s"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"fmmla_z_zzz_d"_h, &Disassembler::Disassemble_ZdaT_ZnT_ZmT}, - {"smmla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB}, - {"ummla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB}, - {"usmmla_z_zzz"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB}, - {"usdot_z_zzz_s"_h, &Disassembler::Disassemble_ZdaS_ZnB_ZmB}, - {"smmla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B}, - {"ummla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B}, - {"usmmla_asimdsame2_g"_h, &Disassembler::Disassemble_Vd4S_Vn16B_Vm16B}, - {"ld1row_z_p_bi_u32"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, - {"ld1row_z_p_br_contiguous"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, - {"ld1rod_z_p_bi_u64"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, - {"ld1rod_z_p_br_contiguous"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, - {"ld1rob_z_p_bi_u8"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, - {"ld1rob_z_p_br_contiguous"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, - {"ld1roh_z_p_bi_u16"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, - {"ld1roh_z_p_br_contiguous"_h, - &Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, - {"usdot_z_zzzi_s"_h, &Disassembler::VisitSVEMulIndex}, - {"sudot_z_zzzi_s"_h, &Disassembler::VisitSVEMulIndex}, - {"usdot_asimdsame2_d"_h, &Disassembler::VisitNEON3SameExtra}, - {"addg_64_addsub_immtags"_h, - &Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4}, - {"gmi_64g_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_Xm}, - {"irg_64i_dp_2src"_h, &Disassembler::Disassemble_XdSP_XnSP_Xm}, - {"ldg_64loffset_ldsttags"_h, &Disassembler::DisassembleMTELoadTag}, - {"st2g_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"st2g_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"st2g_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stgp_64_ldstpair_off"_h, &Disassembler::DisassembleMTEStoreTagPair}, - {"stgp_64_ldstpair_post"_h, &Disassembler::DisassembleMTEStoreTagPair}, - {"stgp_64_ldstpair_pre"_h, &Disassembler::DisassembleMTEStoreTagPair}, - {"stg_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stg_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stg_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stz2g_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stz2g_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stz2g_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stzg_64soffset_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stzg_64spost_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"stzg_64spre_ldsttags"_h, &Disassembler::DisassembleMTEStoreTag}, - {"subg_64_addsub_immtags"_h, - &Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4}, - {"subps_64s_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_XmSP}, - {"subp_64s_dp_2src"_h, &Disassembler::Disassemble_Xd_XnSP_XmSP}, - {"cpyen_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyern_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyewn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpye_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfen_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfern_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfewn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfe_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfmn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfmrn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfmwn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfm_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfpn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfprn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfpwn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyfp_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpymn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpymrn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpymwn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpym_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpypn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyprn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpypwn_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"cpyp_cpy_memcms"_h, &Disassembler::DisassembleCpy}, - {"seten_set_memcms"_h, &Disassembler::DisassembleSet}, - {"sete_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setgen_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setge_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setgmn_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setgm_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setgpn_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setgp_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setmn_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setm_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setpn_set_memcms"_h, &Disassembler::DisassembleSet}, - {"setp_set_memcms"_h, &Disassembler::DisassembleSet}, - {"abs_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"abs_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"cnt_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"cnt_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"ctz_32_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"ctz_64_dp_1src"_h, &Disassembler::VisitDataProcessing1Source}, - {"smax_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"smax_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"smin_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"smin_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"umax_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"umax_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"umin_32_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"umin_64_dp_2src"_h, &Disassembler::VisitDataProcessing2Source}, - {"smax_32_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"smax_64_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"smin_32_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"smin_64_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"umax_32u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"umax_64u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"umin_32u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"umin_64u_minmax_imm"_h, &Disassembler::DisassembleMinMaxImm}, - {"bcax_vvv16_crypto4"_h, &Disassembler::DisassembleNEON4Same}, - {"eor3_vvv16_crypto4"_h, &Disassembler::DisassembleNEON4Same}, - {"xar_vvv2_crypto3_imm6"_h, &Disassembler::DisassembleNEONXar}, - {"rax1_vvv2_cryptosha512_3"_h, &Disassembler::DisassembleNEONRax1}, - {"sha512h2_qqv_cryptosha512_3"_h, &Disassembler::DisassembleSHA512}, - {"sha512h_qqv_cryptosha512_3"_h, &Disassembler::DisassembleSHA512}, - {"sha512su0_vv2_cryptosha512_2"_h, &Disassembler::DisassembleSHA512}, - {"sha512su1_vvv2_cryptosha512_3"_h, &Disassembler::DisassembleSHA512}, }; return &form_to_visitor; } // NOLINT(readability/fn_size) @@ -771,6 +3283,8 @@ Disassembler::Disassembler() { buffer_pos_ = 0; own_buffer_ = true; code_address_offset_ = 0; + + PopulateFormToStringMap(&form_to_string_); } Disassembler::Disassembler(char *text_buffer, int buffer_size) { @@ -779,6 +3293,8 @@ Disassembler::Disassembler(char *text_buffer, int buffer_size) { buffer_pos_ = 0; own_buffer_ = false; code_address_offset_ = 0; + + PopulateFormToStringMap(&form_to_string_); } Disassembler::~Disassembler() { @@ -789,227 +3305,6 @@ Disassembler::~Disassembler() { char *Disassembler::GetOutput() { return buffer_; } -void Disassembler::VisitAddSubImmediate(const Instruction *instr) { - bool rd_is_zr = RdIsZROrSP(instr); - bool stack_op = - (rd_is_zr || RnIsZROrSP(instr)) && (instr->GetImmAddSub() == 0) ? true - : false; - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Rds, 'Rns, 'IAddSub"; - const char *form_cmp = "'Rns, 'IAddSub"; - const char *form_mov = "'Rds, 'Rns"; - - switch (form_hash_) { - case "add_32_addsub_imm"_h: - case "add_64_addsub_imm"_h: - if (stack_op) { - mnemonic = "mov"; - form = form_mov; - } - break; - case "adds_32s_addsub_imm"_h: - case "adds_64s_addsub_imm"_h: - if (rd_is_zr) { - mnemonic = "cmn"; - form = form_cmp; - } - break; - case "subs_32s_addsub_imm"_h: - case "subs_64s_addsub_imm"_h: - if (rd_is_zr) { - mnemonic = "cmp"; - form = form_cmp; - } - break; - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitAddSubShifted(const Instruction *instr) { - bool rd_is_zr = RdIsZROrSP(instr); - bool rn_is_zr = RnIsZROrSP(instr); - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Rd, 'Rn, 'Rm'NDP"; - const char *form_cmp = "'Rn, 'Rm'NDP"; - const char *form_neg = "'Rd, 'Rm'NDP"; - - if (instr->GetShiftDP() == ROR) { - // Add/sub/adds/subs don't allow ROR as a shift mode. - VisitUnallocated(instr); - return; - } - - switch (form_hash_) { - case "adds_32_addsub_shift"_h: - case "adds_64_addsub_shift"_h: - if (rd_is_zr) { - mnemonic = "cmn"; - form = form_cmp; - } - break; - case "sub_32_addsub_shift"_h: - case "sub_64_addsub_shift"_h: - if (rn_is_zr) { - mnemonic = "neg"; - form = form_neg; - } - break; - case "subs_32_addsub_shift"_h: - case "subs_64_addsub_shift"_h: - if (rd_is_zr) { - mnemonic = "cmp"; - form = form_cmp; - } else if (rn_is_zr) { - mnemonic = "negs"; - form = form_neg; - } - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitAddSubExtended(const Instruction *instr) { - bool rd_is_zr = RdIsZROrSP(instr); - const char *mnemonic = ""; - Extend mode = static_cast(instr->GetExtendMode()); - const char *form = ((mode == UXTX) || (mode == SXTX)) ? "'Rds, 'Rns, 'Xm'Ext" - : "'Rds, 'Rns, 'Wm'Ext"; - const char *form_cmp = - ((mode == UXTX) || (mode == SXTX)) ? "'Rns, 'Xm'Ext" : "'Rns, 'Wm'Ext"; - - switch (instr->Mask(AddSubExtendedMask)) { - case ADD_w_ext: - case ADD_x_ext: - mnemonic = "add"; - break; - case ADDS_w_ext: - case ADDS_x_ext: { - mnemonic = "adds"; - if (rd_is_zr) { - mnemonic = "cmn"; - form = form_cmp; - } - break; - } - case SUB_w_ext: - case SUB_x_ext: - mnemonic = "sub"; - break; - case SUBS_w_ext: - case SUBS_x_ext: { - mnemonic = "subs"; - if (rd_is_zr) { - mnemonic = "cmp"; - form = form_cmp; - } - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitAddSubWithCarry(const Instruction *instr) { - bool rn_is_zr = RnIsZROrSP(instr); - const char *mnemonic = ""; - const char *form = "'Rd, 'Rn, 'Rm"; - const char *form_neg = "'Rd, 'Rm"; - - switch (instr->Mask(AddSubWithCarryMask)) { - case ADC_w: - case ADC_x: - mnemonic = "adc"; - break; - case ADCS_w: - case ADCS_x: - mnemonic = "adcs"; - break; - case SBC_w: - case SBC_x: { - mnemonic = "sbc"; - if (rn_is_zr) { - mnemonic = "ngc"; - form = form_neg; - } - break; - } - case SBCS_w: - case SBCS_x: { - mnemonic = "sbcs"; - if (rn_is_zr) { - mnemonic = "ngcs"; - form = form_neg; - } - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitRotateRightIntoFlags(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Xn, 'IRr, 'INzcv"); -} - - -void Disassembler::VisitEvaluateIntoFlags(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Wn"); -} - - -void Disassembler::VisitLogicalImmediate(const Instruction *instr) { - bool rd_is_zr = RdIsZROrSP(instr); - bool rn_is_zr = RnIsZROrSP(instr); - const char *mnemonic = ""; - const char *form = "'Rds, 'Rn, 'ITri"; - - if (instr->GetImmLogical() == 0) { - // The immediate encoded in the instruction is not in the expected format. - Format(instr, "unallocated", "(LogicalImmediate)"); - return; - } - - switch (instr->Mask(LogicalImmediateMask)) { - case AND_w_imm: - case AND_x_imm: - mnemonic = "and"; - break; - case ORR_w_imm: - case ORR_x_imm: { - mnemonic = "orr"; - unsigned reg_size = - (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize; - if (rn_is_zr && !IsMovzMovnImm(reg_size, instr->GetImmLogical())) { - mnemonic = "mov"; - form = "'Rds, 'ITri"; - } - break; - } - case EOR_w_imm: - case EOR_x_imm: - mnemonic = "eor"; - break; - case ANDS_w_imm: - case ANDS_x_imm: { - mnemonic = "ands"; - if (rd_is_zr) { - mnemonic = "tst"; - form = "'Rn, 'ITri"; - } - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { VIXL_ASSERT((reg_size == kXRegSize) || ((reg_size == kWRegSize) && (value <= 0xffffffff))); @@ -1037,2960 +3332,6 @@ bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { return false; } - -void Disassembler::VisitLogicalShifted(const Instruction *instr) { - bool rd_is_zr = RdIsZROrSP(instr); - bool rn_is_zr = RnIsZROrSP(instr); - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Rd, 'Rn, 'Rm'NLo"; - - switch (form_hash_) { - case "ands_32_log_shift"_h: - case "ands_64_log_shift"_h: - if (rd_is_zr) { - mnemonic = "tst"; - form = "'Rn, 'Rm'NLo"; - } - break; - case "orr_32_log_shift"_h: - case "orr_64_log_shift"_h: - if (rn_is_zr && (instr->GetImmDPShift() == 0) && - (instr->GetShiftDP() == LSL)) { - mnemonic = "mov"; - form = "'Rd, 'Rm"; - } - break; - case "orn_32_log_shift"_h: - case "orn_64_log_shift"_h: - if (rn_is_zr) { - mnemonic = "mvn"; - form = "'Rd, 'Rm'NLo"; - } - break; - } - - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitConditionalCompareRegister(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Rn, 'Rm, 'INzcv, 'Cond"); -} - - -void Disassembler::VisitConditionalCompareImmediate(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Rn, 'IP, 'INzcv, 'Cond"); -} - - -void Disassembler::VisitConditionalSelect(const Instruction *instr) { - bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr)); - bool rn_is_rm = (instr->GetRn() == instr->GetRm()); - const char *mnemonic = ""; - const char *form = "'Rd, 'Rn, 'Rm, 'Cond"; - const char *form_test = "'Rd, 'CInv"; - const char *form_update = "'Rd, 'Rn, 'CInv"; - - Condition cond = static_cast(instr->GetCondition()); - bool invertible_cond = (cond != al) && (cond != nv); - - switch (instr->Mask(ConditionalSelectMask)) { - case CSEL_w: - case CSEL_x: - mnemonic = "csel"; - break; - case CSINC_w: - case CSINC_x: { - mnemonic = "csinc"; - if (rnm_is_zr && invertible_cond) { - mnemonic = "cset"; - form = form_test; - } else if (rn_is_rm && invertible_cond) { - mnemonic = "cinc"; - form = form_update; - } - break; - } - case CSINV_w: - case CSINV_x: { - mnemonic = "csinv"; - if (rnm_is_zr && invertible_cond) { - mnemonic = "csetm"; - form = form_test; - } else if (rn_is_rm && invertible_cond) { - mnemonic = "cinv"; - form = form_update; - } - break; - } - case CSNEG_w: - case CSNEG_x: { - mnemonic = "csneg"; - if (rn_is_rm && invertible_cond) { - mnemonic = "cneg"; - form = form_update; - } - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitBitfield(const Instruction *instr) { - unsigned s = instr->GetImmS(); - unsigned r = instr->GetImmR(); - unsigned rd_size_minus_1 = - ((instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize) - 1; - const char *mnemonic = ""; - const char *form = ""; - const char *form_shift_right = "'Rd, 'Rn, 'IBr"; - const char *form_extend = "'Rd, 'Wn"; - const char *form_bfiz = "'Rd, 'Rn, 'IBZ-r, 'IBs+1"; - const char *form_bfc = "'Rd, 'IBZ-r, 'IBs+1"; - const char *form_bfx = "'Rd, 'Rn, 'IBr, 'IBs-r+1"; - const char *form_lsl = "'Rd, 'Rn, 'IBZ-r"; - - if (instr->GetSixtyFourBits() != instr->GetBitN()) { - VisitUnallocated(instr); - return; - } - - if ((instr->GetSixtyFourBits() == 0) && ((s > 31) || (r > 31))) { - VisitUnallocated(instr); - return; - } - - switch (instr->Mask(BitfieldMask)) { - case SBFM_w: - case SBFM_x: { - mnemonic = "sbfx"; - form = form_bfx; - if (r == 0) { - form = form_extend; - if (s == 7) { - mnemonic = "sxtb"; - } else if (s == 15) { - mnemonic = "sxth"; - } else if ((s == 31) && (instr->GetSixtyFourBits() == 1)) { - mnemonic = "sxtw"; - } else { - form = form_bfx; - } - } else if (s == rd_size_minus_1) { - mnemonic = "asr"; - form = form_shift_right; - } else if (s < r) { - mnemonic = "sbfiz"; - form = form_bfiz; - } - break; - } - case UBFM_w: - case UBFM_x: { - mnemonic = "ubfx"; - form = form_bfx; - if (r == 0) { - form = form_extend; - if (s == 7) { - mnemonic = "uxtb"; - } else if (s == 15) { - mnemonic = "uxth"; - } else { - form = form_bfx; - } - } - if (s == rd_size_minus_1) { - mnemonic = "lsr"; - form = form_shift_right; - } else if (r == s + 1) { - mnemonic = "lsl"; - form = form_lsl; - } else if (s < r) { - mnemonic = "ubfiz"; - form = form_bfiz; - } - break; - } - case BFM_w: - case BFM_x: { - mnemonic = "bfxil"; - form = form_bfx; - if (s < r) { - if (instr->GetRn() == kZeroRegCode) { - mnemonic = "bfc"; - form = form_bfc; - } else { - mnemonic = "bfi"; - form = form_bfiz; - } - } - } - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitExtract(const Instruction *instr) { - const char *mnemonic = ""; - const char *form = "'Rd, 'Rn, 'Rm, 'IExtract"; - - switch (instr->Mask(ExtractMask)) { - case EXTR_w: - case EXTR_x: { - if (instr->GetRn() == instr->GetRm()) { - mnemonic = "ror"; - form = "'Rd, 'Rn, 'IExtract"; - } else { - mnemonic = "extr"; - } - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitPCRelAddressing(const Instruction *instr) { - switch (instr->Mask(PCRelAddressingMask)) { - case ADR: - Format(instr, "adr", "'Xd, 'AddrPCRelByte"); - break; - case ADRP: - Format(instr, "adrp", "'Xd, 'AddrPCRelPage"); - break; - default: - Format(instr, "unimplemented", "(PCRelAddressing)"); - } -} - - -void Disassembler::VisitConditionalBranch(const Instruction *instr) { - // We can't use the mnemonic directly here, as there's no space between it and - // the condition. Assert that we have the correct mnemonic, then use "b" - // explicitly for formatting the output. - VIXL_ASSERT(form_hash_ == "b_only_condbranch"_h); - Format(instr, "b.'CBrn", "'TImmCond"); -} - - -void Disassembler::VisitUnconditionalBranchToRegister( - const Instruction *instr) { - const char *form = "'Xn"; - - switch (form_hash_) { - case "ret_64r_branch_reg"_h: - if (instr->GetRn() == kLinkRegCode) { - form = ""; - } - break; - case "retaa_64e_branch_reg"_h: - case "retab_64e_branch_reg"_h: - form = ""; - break; - case "braa_64p_branch_reg"_h: - case "brab_64p_branch_reg"_h: - case "blraa_64p_branch_reg"_h: - case "blrab_64p_branch_reg"_h: - form = "'Xn, 'Xds"; - break; - } - - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitUnconditionalBranch(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'TImmUncn"); -} - - -void Disassembler::VisitDataProcessing1Source(const Instruction *instr) { - const char *form = "'Rd, 'Rn"; - - switch (form_hash_) { - case "pacia_64p_dp_1src"_h: - case "pacda_64p_dp_1src"_h: - case "autia_64p_dp_1src"_h: - case "autda_64p_dp_1src"_h: - case "pacib_64p_dp_1src"_h: - case "pacdb_64p_dp_1src"_h: - case "autib_64p_dp_1src"_h: - case "autdb_64p_dp_1src"_h: - form = "'Xd, 'Xns"; - break; - case "paciza_64z_dp_1src"_h: - case "pacdza_64z_dp_1src"_h: - case "autiza_64z_dp_1src"_h: - case "autdza_64z_dp_1src"_h: - case "pacizb_64z_dp_1src"_h: - case "pacdzb_64z_dp_1src"_h: - case "autizb_64z_dp_1src"_h: - case "autdzb_64z_dp_1src"_h: - case "xpacd_64z_dp_1src"_h: - case "xpaci_64z_dp_1src"_h: - form = "'Xd"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitDataProcessing2Source(const Instruction *instr) { - std::string mnemonic = mnemonic_; - const char *form = "'Rd, 'Rn, 'Rm"; - - switch (form_hash_) { - case "asrv_32_dp_2src"_h: - case "asrv_64_dp_2src"_h: - case "lslv_32_dp_2src"_h: - case "lslv_64_dp_2src"_h: - case "lsrv_32_dp_2src"_h: - case "lsrv_64_dp_2src"_h: - case "rorv_32_dp_2src"_h: - case "rorv_64_dp_2src"_h: - // Drop the last 'v' character. - VIXL_ASSERT(mnemonic[3] == 'v'); - mnemonic.pop_back(); - break; - case "pacga_64p_dp_2src"_h: - form = "'Xd, 'Xn, 'Xms"; - break; - case "crc32x_64c_dp_2src"_h: - case "crc32cx_64c_dp_2src"_h: - form = "'Wd, 'Wn, 'Xm"; - break; - } - Format(instr, mnemonic.c_str(), form); -} - - -void Disassembler::VisitDataProcessing3Source(const Instruction *instr) { - bool ra_is_zr = RaIsZROrSP(instr); - const char *mnemonic = ""; - const char *form = "'Xd, 'Wn, 'Wm, 'Xa"; - const char *form_rrr = "'Rd, 'Rn, 'Rm"; - const char *form_rrrr = "'Rd, 'Rn, 'Rm, 'Ra"; - const char *form_xww = "'Xd, 'Wn, 'Wm"; - const char *form_xxx = "'Xd, 'Xn, 'Xm"; - - switch (instr->Mask(DataProcessing3SourceMask)) { - case MADD_w: - case MADD_x: { - mnemonic = "madd"; - form = form_rrrr; - if (ra_is_zr) { - mnemonic = "mul"; - form = form_rrr; - } - break; - } - case MSUB_w: - case MSUB_x: { - mnemonic = "msub"; - form = form_rrrr; - if (ra_is_zr) { - mnemonic = "mneg"; - form = form_rrr; - } - break; - } - case SMADDL_x: { - mnemonic = "smaddl"; - if (ra_is_zr) { - mnemonic = "smull"; - form = form_xww; - } - break; - } - case SMSUBL_x: { - mnemonic = "smsubl"; - if (ra_is_zr) { - mnemonic = "smnegl"; - form = form_xww; - } - break; - } - case UMADDL_x: { - mnemonic = "umaddl"; - if (ra_is_zr) { - mnemonic = "umull"; - form = form_xww; - } - break; - } - case UMSUBL_x: { - mnemonic = "umsubl"; - if (ra_is_zr) { - mnemonic = "umnegl"; - form = form_xww; - } - break; - } - case SMULH_x: { - mnemonic = "smulh"; - form = form_xxx; - break; - } - case UMULH_x: { - mnemonic = "umulh"; - form = form_xxx; - break; - } - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - -void Disassembler::DisassembleMinMaxImm(const Instruction *instr) { - const char *suffix = (instr->ExtractBit(18) == 0) ? "'s1710" : "'u1710"; - FormatWithDecodedMnemonic(instr, "'Rd, 'Rn, #", suffix); -} - -void Disassembler::VisitCompareBranch(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Rt, 'TImmCmpa"); -} - - -void Disassembler::VisitTestBranch(const Instruction *instr) { - // If the top bit of the immediate is clear, the tested register is - // disassembled as Wt, otherwise Xt. As the top bit of the immediate is - // encoded in bit 31 of the instruction, we can reuse the Rt form, which - // uses bit 31 (normally "sf") to choose the register size. - FormatWithDecodedMnemonic(instr, "'Rt, 'It, 'TImmTest"); -} - - -void Disassembler::VisitMoveWideImmediate(const Instruction *instr) { - const char *mnemonic = ""; - const char *form = "'Rd, 'IMoveImm"; - - // Print the shift separately for movk, to make it clear which half word will - // be overwritten. Movn and movz print the computed immediate, which includes - // shift calculation. - switch (instr->Mask(MoveWideImmediateMask)) { - case MOVN_w: - case MOVN_x: - if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) { - if ((instr->GetSixtyFourBits() == 0) && - (instr->GetImmMoveWide() == 0xffff)) { - mnemonic = "movn"; - } else { - mnemonic = "mov"; - form = "'Rd, 'IMoveNeg"; - } - } else { - mnemonic = "movn"; - } - break; - case MOVZ_w: - case MOVZ_x: - if ((instr->GetImmMoveWide()) || (instr->GetShiftMoveWide() == 0)) - mnemonic = "mov"; - else - mnemonic = "movz"; - break; - case MOVK_w: - case MOVK_x: - mnemonic = "movk"; - form = "'Rd, 'IMoveLSL"; - break; - default: - VIXL_UNREACHABLE(); - } - Format(instr, mnemonic, form); -} - - -#define LOAD_STORE_LIST(V) \ - V(STRB_w, "'Wt") \ - V(STRH_w, "'Wt") \ - V(STR_w, "'Wt") \ - V(STR_x, "'Xt") \ - V(LDRB_w, "'Wt") \ - V(LDRH_w, "'Wt") \ - V(LDR_w, "'Wt") \ - V(LDR_x, "'Xt") \ - V(LDRSB_x, "'Xt") \ - V(LDRSH_x, "'Xt") \ - V(LDRSW_x, "'Xt") \ - V(LDRSB_w, "'Wt") \ - V(LDRSH_w, "'Wt") \ - V(STR_b, "'Bt") \ - V(STR_h, "'Ht") \ - V(STR_s, "'St") \ - V(STR_d, "'Dt") \ - V(LDR_b, "'Bt") \ - V(LDR_h, "'Ht") \ - V(LDR_s, "'St") \ - V(LDR_d, "'Dt") \ - V(STR_q, "'Qt") \ - V(LDR_q, "'Qt") - -void Disassembler::VisitLoadStorePreIndex(const Instruction *instr) { - const char *form = "(LoadStorePreIndex)"; - const char *suffix = ", ['Xns'ILSi]!"; - - switch (instr->Mask(LoadStorePreIndexMask)) { -#define LS_PREINDEX(A, B) \ - case A##_pre: \ - form = B; \ - break; - LOAD_STORE_LIST(LS_PREINDEX) -#undef LS_PREINDEX - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitLoadStorePostIndex(const Instruction *instr) { - const char *form = "(LoadStorePostIndex)"; - const char *suffix = ", ['Xns]'ILSi"; - - switch (instr->Mask(LoadStorePostIndexMask)) { -#define LS_POSTINDEX(A, B) \ - case A##_post: \ - form = B; \ - break; - LOAD_STORE_LIST(LS_POSTINDEX) -#undef LS_POSTINDEX - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction *instr) { - const char *form = "(LoadStoreUnsignedOffset)"; - const char *suffix = ", ['Xns'ILU]"; - - switch (instr->Mask(LoadStoreUnsignedOffsetMask)) { -#define LS_UNSIGNEDOFFSET(A, B) \ - case A##_unsigned: \ - form = B; \ - break; - LOAD_STORE_LIST(LS_UNSIGNEDOFFSET) -#undef LS_UNSIGNEDOFFSET - case PRFM_unsigned: - form = "'prefOp"; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitLoadStoreRCpcUnscaledOffset(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Wt, ['Xns'ILS]"; - const char *form_x = "'Xt, ['Xns'ILS]"; - - switch (form_hash_) { - case "ldapursb_64_ldapstl_unscaled"_h: - case "ldapursh_64_ldapstl_unscaled"_h: - case "ldapursw_64_ldapstl_unscaled"_h: - case "ldapur_64_ldapstl_unscaled"_h: - case "stlur_64_ldapstl_unscaled"_h: - form = form_x; - break; - } - - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitLoadStoreRegisterOffset(const Instruction *instr) { - const char *form = "(LoadStoreRegisterOffset)"; - const char *suffix = ", ['Xns, 'Offsetreg]"; - - switch (instr->Mask(LoadStoreRegisterOffsetMask)) { -#define LS_REGISTEROFFSET(A, B) \ - case A##_reg: \ - form = B; \ - break; - LOAD_STORE_LIST(LS_REGISTEROFFSET) -#undef LS_REGISTEROFFSET - case PRFM_reg: - form = "'prefOp"; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction *instr) { - const char *form = "'Wt"; - const char *suffix = ", ['Xns'ILS]"; - - switch (form_hash_) { - case "ldur_64_ldst_unscaled"_h: - case "ldursb_64_ldst_unscaled"_h: - case "ldursh_64_ldst_unscaled"_h: - case "ldursw_64_ldst_unscaled"_h: - case "stur_64_ldst_unscaled"_h: - form = "'Xt"; - break; - case "ldur_b_ldst_unscaled"_h: - case "stur_b_ldst_unscaled"_h: - form = "'Bt"; - break; - case "ldur_h_ldst_unscaled"_h: - case "stur_h_ldst_unscaled"_h: - form = "'Ht"; - break; - case "ldur_s_ldst_unscaled"_h: - case "stur_s_ldst_unscaled"_h: - form = "'St"; - break; - case "ldur_d_ldst_unscaled"_h: - case "stur_d_ldst_unscaled"_h: - form = "'Dt"; - break; - case "ldur_q_ldst_unscaled"_h: - case "stur_q_ldst_unscaled"_h: - form = "'Qt"; - break; - case "prfum_p_ldst_unscaled"_h: - form = "'prefOp"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitLoadLiteral(const Instruction *instr) { - const char *form = "'Wt"; - const char *suffix = ", 'ILLiteral 'LValue"; - - switch (form_hash_) { - case "ldr_64_loadlit"_h: - case "ldrsw_64_loadlit"_h: - form = "'Xt"; - break; - case "ldr_s_loadlit"_h: - form = "'St"; - break; - case "ldr_d_loadlit"_h: - form = "'Dt"; - break; - case "ldr_q_loadlit"_h: - form = "'Qt"; - break; - case "prfm_p_loadlit"_h: - form = "'prefOp"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -#define LOAD_STORE_PAIR_LIST(V) \ - V(STP_w, "'Wt, 'Wt2", "2") \ - V(LDP_w, "'Wt, 'Wt2", "2") \ - V(LDPSW_x, "'Xt, 'Xt2", "2") \ - V(STP_x, "'Xt, 'Xt2", "3") \ - V(LDP_x, "'Xt, 'Xt2", "3") \ - V(STP_s, "'St, 'St2", "2") \ - V(LDP_s, "'St, 'St2", "2") \ - V(STP_d, "'Dt, 'Dt2", "3") \ - V(LDP_d, "'Dt, 'Dt2", "3") \ - V(LDP_q, "'Qt, 'Qt2", "4") \ - V(STP_q, "'Qt, 'Qt2", "4") - -void Disassembler::VisitLoadStorePairPostIndex(const Instruction *instr) { - const char *form = "(LoadStorePairPostIndex)"; - - switch (instr->Mask(LoadStorePairPostIndexMask)) { -#define LSP_POSTINDEX(A, B, C) \ - case A##_post: \ - form = B ", ['Xns]'ILP" C "i"; \ - break; - LOAD_STORE_PAIR_LIST(LSP_POSTINDEX) -#undef LSP_POSTINDEX - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitLoadStorePairPreIndex(const Instruction *instr) { - const char *form = "(LoadStorePairPreIndex)"; - - switch (instr->Mask(LoadStorePairPreIndexMask)) { -#define LSP_PREINDEX(A, B, C) \ - case A##_pre: \ - form = B ", ['Xns'ILP" C "i]!"; \ - break; - LOAD_STORE_PAIR_LIST(LSP_PREINDEX) -#undef LSP_PREINDEX - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitLoadStorePairOffset(const Instruction *instr) { - const char *form = "(LoadStorePairOffset)"; - - switch (instr->Mask(LoadStorePairOffsetMask)) { -#define LSP_OFFSET(A, B, C) \ - case A##_off: \ - form = B ", ['Xns'ILP" C "]"; \ - break; - LOAD_STORE_PAIR_LIST(LSP_OFFSET) -#undef LSP_OFFSET - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitLoadStorePairNonTemporal(const Instruction *instr) { - const char *form = "'Wt, 'Wt2, ['Xns'ILP2]"; - - switch (form_hash_) { - case "ldnp_64_ldstnapair_offs"_h: - case "stnp_64_ldstnapair_offs"_h: - form = "'Xt, 'Xt2, ['Xns'ILP3]"; - break; - case "ldnp_s_ldstnapair_offs"_h: - case "stnp_s_ldstnapair_offs"_h: - form = "'St, 'St2, ['Xns'ILP2]"; - break; - case "ldnp_d_ldstnapair_offs"_h: - case "stnp_d_ldstnapair_offs"_h: - form = "'Dt, 'Dt2, ['Xns'ILP3]"; - break; - case "ldnp_q_ldstnapair_offs"_h: - case "stnp_q_ldstnapair_offs"_h: - form = "'Qt, 'Qt2, ['Xns'ILP4]"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -// clang-format off -#define LOAD_STORE_EXCLUSIVE_LIST(V) \ - V(STXRB_w, "'Ws, 'Wt") \ - V(STXRH_w, "'Ws, 'Wt") \ - V(STXR_w, "'Ws, 'Wt") \ - V(STXR_x, "'Ws, 'Xt") \ - V(LDXR_x, "'Xt") \ - V(STXP_w, "'Ws, 'Wt, 'Wt2") \ - V(STXP_x, "'Ws, 'Xt, 'Xt2") \ - V(LDXP_w, "'Wt, 'Wt2") \ - V(LDXP_x, "'Xt, 'Xt2") \ - V(STLXRB_w, "'Ws, 'Wt") \ - V(STLXRH_w, "'Ws, 'Wt") \ - V(STLXR_w, "'Ws, 'Wt") \ - V(STLXR_x, "'Ws, 'Xt") \ - V(LDAXR_x, "'Xt") \ - V(STLXP_w, "'Ws, 'Wt, 'Wt2") \ - V(STLXP_x, "'Ws, 'Xt, 'Xt2") \ - V(LDAXP_w, "'Wt, 'Wt2") \ - V(LDAXP_x, "'Xt, 'Xt2") \ - V(STLR_x, "'Xt") \ - V(LDAR_x, "'Xt") \ - V(STLLR_x, "'Xt") \ - V(LDLAR_x, "'Xt") \ - V(CAS_w, "'Ws, 'Wt") \ - V(CAS_x, "'Xs, 'Xt") \ - V(CASA_w, "'Ws, 'Wt") \ - V(CASA_x, "'Xs, 'Xt") \ - V(CASL_w, "'Ws, 'Wt") \ - V(CASL_x, "'Xs, 'Xt") \ - V(CASAL_w, "'Ws, 'Wt") \ - V(CASAL_x, "'Xs, 'Xt") \ - V(CASB, "'Ws, 'Wt") \ - V(CASAB, "'Ws, 'Wt") \ - V(CASLB, "'Ws, 'Wt") \ - V(CASALB, "'Ws, 'Wt") \ - V(CASH, "'Ws, 'Wt") \ - V(CASAH, "'Ws, 'Wt") \ - V(CASLH, "'Ws, 'Wt") \ - V(CASALH, "'Ws, 'Wt") \ - V(CASP_w, "'Ws, 'Ws+, 'Wt, 'Wt+") \ - V(CASP_x, "'Xs, 'Xs+, 'Xt, 'Xt+") \ - V(CASPA_w, "'Ws, 'Ws+, 'Wt, 'Wt+") \ - V(CASPA_x, "'Xs, 'Xs+, 'Xt, 'Xt+") \ - V(CASPL_w, "'Ws, 'Ws+, 'Wt, 'Wt+") \ - V(CASPL_x, "'Xs, 'Xs+, 'Xt, 'Xt+") \ - V(CASPAL_w, "'Ws, 'Ws+, 'Wt, 'Wt+") \ - V(CASPAL_x, "'Xs, 'Xs+, 'Xt, 'Xt+") -// clang-format on - - -void Disassembler::VisitLoadStoreExclusive(const Instruction *instr) { - const char *form = "'Wt"; - const char *suffix = ", ['Xns]"; - - switch (instr->Mask(LoadStoreExclusiveMask)) { -#define LSX(A, B) \ - case A: \ - form = B; \ - break; - LOAD_STORE_EXCLUSIVE_LIST(LSX) -#undef LSX - } - - switch (instr->Mask(LoadStoreExclusiveMask)) { - case CASP_w: - case CASP_x: - case CASPA_w: - case CASPA_x: - case CASPL_w: - case CASPL_x: - case CASPAL_w: - case CASPAL_x: - if ((instr->GetRs() % 2 == 1) || (instr->GetRt() % 2 == 1)) { - VisitUnallocated(instr); - return; - } - break; - } - - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitLoadStorePAC(const Instruction *instr) { - const char *form = "'Xt, ['Xns'ILA]"; - const char *suffix = ""; - switch (form_hash_) { - case "ldraa_64w_ldst_pac"_h: - case "ldrab_64w_ldst_pac"_h: - suffix = "!"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitAtomicMemory(const Instruction *instr) { - bool is_x = (instr->ExtractBits(31, 30) == 3); - const char *form = is_x ? "'Xs, 'Xt" : "'Ws, 'Wt"; - const char *suffix = ", ['Xns]"; - - std::string mnemonic = mnemonic_; - - switch (form_hash_) { - case "ldaprb_32l_memop"_h: - case "ldaprh_32l_memop"_h: - case "ldapr_32l_memop"_h: - form = "'Wt"; - break; - case "ldapr_64l_memop"_h: - form = "'Xt"; - break; - default: - // Zero register implies a store instruction. - if (instr->GetRt() == kZeroRegCode) { - mnemonic.replace(0, 2, "st"); - form = is_x ? "'Xs" : "'Ws"; - } - } - Format(instr, mnemonic.c_str(), form, suffix); -} - - -void Disassembler::VisitFPCompare(const Instruction *instr) { - const char *form = "'Fn, 'Fm"; - switch (form_hash_) { - case "fcmpe_dz_floatcmp"_h: - case "fcmpe_hz_floatcmp"_h: - case "fcmpe_sz_floatcmp"_h: - case "fcmp_dz_floatcmp"_h: - case "fcmp_hz_floatcmp"_h: - case "fcmp_sz_floatcmp"_h: - form = "'Fn, #0.0"; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitFPConditionalCompare(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Fn, 'Fm, 'INzcv, 'Cond"); -} - - -void Disassembler::VisitFPConditionalSelect(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm, 'Cond"); -} - - -void Disassembler::VisitFPDataProcessing1Source(const Instruction *instr) { - const char *form = "'Fd, 'Fn"; - switch (form_hash_) { - case "fcvt_ds_floatdp1"_h: - form = "'Dd, 'Sn"; - break; - case "fcvt_sd_floatdp1"_h: - form = "'Sd, 'Dn"; - break; - case "fcvt_hs_floatdp1"_h: - form = "'Hd, 'Sn"; - break; - case "fcvt_sh_floatdp1"_h: - form = "'Sd, 'Hn"; - break; - case "fcvt_dh_floatdp1"_h: - form = "'Dd, 'Hn"; - break; - case "fcvt_hd_floatdp1"_h: - form = "'Hd, 'Dn"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitFPDataProcessing2Source(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm"); -} - - -void Disassembler::VisitFPDataProcessing3Source(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Fd, 'Fn, 'Fm, 'Fa"); -} - - -void Disassembler::VisitFPImmediate(const Instruction *instr) { - const char *form = "'Hd"; - const char *suffix = ", 'IFP"; - switch (form_hash_) { - case "fmov_s_floatimm"_h: - form = "'Sd"; - break; - case "fmov_d_floatimm"_h: - form = "'Dd"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - - -void Disassembler::VisitFPIntegerConvert(const Instruction *instr) { - const char *form = "'Rd, 'Fn"; - switch (form_hash_) { - case "fmov_h32_float2int"_h: - case "fmov_h64_float2int"_h: - case "fmov_s32_float2int"_h: - case "fmov_d64_float2int"_h: - case "scvtf_d32_float2int"_h: - case "scvtf_d64_float2int"_h: - case "scvtf_h32_float2int"_h: - case "scvtf_h64_float2int"_h: - case "scvtf_s32_float2int"_h: - case "scvtf_s64_float2int"_h: - case "ucvtf_d32_float2int"_h: - case "ucvtf_d64_float2int"_h: - case "ucvtf_h32_float2int"_h: - case "ucvtf_h64_float2int"_h: - case "ucvtf_s32_float2int"_h: - case "ucvtf_s64_float2int"_h: - form = "'Fd, 'Rn"; - break; - case "fmov_v64i_float2int"_h: - form = "'Vd.D[1], 'Rn"; - break; - case "fmov_64vx_float2int"_h: - form = "'Rd, 'Vn.D[1]"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitFPFixedPointConvert(const Instruction *instr) { - const char *form = "'Rd, 'Fn"; - const char *suffix = ", 'IFPFBits"; - - switch (form_hash_) { - case "scvtf_d32_float2fix"_h: - case "scvtf_d64_float2fix"_h: - case "scvtf_h32_float2fix"_h: - case "scvtf_h64_float2fix"_h: - case "scvtf_s32_float2fix"_h: - case "scvtf_s64_float2fix"_h: - case "ucvtf_d32_float2fix"_h: - case "ucvtf_d64_float2fix"_h: - case "ucvtf_h32_float2fix"_h: - case "ucvtf_h64_float2fix"_h: - case "ucvtf_s32_float2fix"_h: - case "ucvtf_s64_float2fix"_h: - form = "'Fd, 'Rn"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::DisassembleNoArgs(const Instruction *instr) { - Format(instr, mnemonic_.c_str(), ""); -} - -void Disassembler::VisitSystem(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = ""; - const char *suffix = NULL; - - switch (form_hash_) { - case "clrex_bn_barriers"_h: - form = (instr->GetCRm() == 0xf) ? "" : "'IX"; - break; - case "mrs_rs_systemmove"_h: - form = "'Xt, 'IY"; - break; - case "msr_sr_systemmove"_h: - form = "'IY, 'Xt"; - break; - case "bti_hb_hints"_h: - switch (instr->ExtractBits(7, 6)) { - case 0: - form = ""; - break; - case 1: - form = "c"; - break; - case 2: - form = "j"; - break; - case 3: - form = "jc"; - break; - } - break; - case "chkfeat_hf_hints"_h: - mnemonic = "chkfeat"; - form = "x16"; - break; - case "hint_hm_hints"_h: - form = "'IH"; - break; - case Hash("dmb_bo_barriers"): - form = "'M"; - break; - case Hash("dsb_bo_barriers"): { - int crm = instr->GetCRm(); - if (crm == 0) { - mnemonic = "ssbb"; - form = ""; - } else if (crm == 4) { - mnemonic = "pssbb"; - form = ""; - } else { - form = "'M"; - } - break; - } - case Hash("sys_cr_systeminstrs"): { - const std::map dcop = { - {IVAU, "ivau"}, - {CVAC, "cvac"}, - {CVAU, "cvau"}, - {CVAP, "cvap"}, - {CVADP, "cvadp"}, - {CIVAC, "civac"}, - {ZVA, "zva"}, - {GVA, "gva"}, - {GZVA, "gzva"}, - {CGVAC, "cgvac"}, - {CGDVAC, "cgdvac"}, - {CGVAP, "cgvap"}, - {CGDVAP, "cgdvap"}, - {CIGVAC, "cigvac"}, - {CIGDVAC, "cigdvac"}, - }; - - uint32_t sysop = instr->GetSysOp(); - if (dcop.count(sysop)) { - if (sysop == IVAU) { - mnemonic = "ic"; - } else { - mnemonic = "dc"; - } - form = dcop.at(sysop); - suffix = ", 'Xt"; - } else if (sysop == GCSSS1) { - mnemonic = "gcsss1"; - form = "'Xt"; - } else if (sysop == GCSPUSHM) { - mnemonic = "gcspushm"; - form = "'Xt"; - } else { - mnemonic = "sys"; - form = "'G1, 'Kn, 'Km, 'G2"; - if (instr->GetRt() < 31) { - suffix = ", 'Xt"; - } - } - break; - } - case "sysl_rc_systeminstrs"_h: - uint32_t sysop = instr->GetSysOp(); - if (sysop == GCSPOPM) { - mnemonic = "gcspopm"; - form = (instr->GetRt() == 31) ? "" : "'Xt"; - } else if (sysop == GCSSS2) { - mnemonic = "gcsss2"; - form = "'Xt"; - } - break; - } - Format(instr, mnemonic, form, suffix); -} - - -void Disassembler::VisitException(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "'IDebug"; - - switch (instr->Mask(ExceptionMask)) { - case HLT: - mnemonic = "hlt"; - break; - case BRK: - mnemonic = "brk"; - break; - case SVC: - mnemonic = "svc"; - break; - case HVC: - mnemonic = "hvc"; - break; - case SMC: - mnemonic = "smc"; - break; - case DCPS1: - mnemonic = "dcps1"; - form = "{'IDebug}"; - break; - case DCPS2: - mnemonic = "dcps2"; - form = "{'IDebug}"; - break; - case DCPS3: - mnemonic = "dcps3"; - form = "{'IDebug}"; - break; - default: - form = "(Exception)"; - } - Format(instr, mnemonic, form); -} - - -void Disassembler::VisitCrypto2RegSHA(const Instruction *instr) { - const char *form = "'Vd.4s, 'Vn.4s"; - if (form_hash_ == "sha1h_ss_cryptosha2"_h) { - form = "'Sd, 'Sn"; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitCrypto3RegSHA(const Instruction *instr) { - const char *form = "'Qd, 'Sn, 'Vm.4s"; - switch (form_hash_) { - case "sha1su0_vvv_cryptosha3"_h: - case "sha256su1_vvv_cryptosha3"_h: - form = "'Vd.4s, 'Vn.4s, 'Vm.4s"; - break; - case "sha256h_qqv_cryptosha3"_h: - case "sha256h2_qqv_cryptosha3"_h: - form = "'Qd, 'Qn, 'Vm.4s"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - - -void Disassembler::VisitCryptoAES(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.16b, 'Vn.16b"); -} - -void Disassembler::VisitCryptoSM3(const Instruction *instr) { - const char *form = "'Vd.4s, 'Vn.4s, 'Vm."; - const char *suffix = "4s"; - - switch (form_hash_) { - case "sm3ss1_vvv4_crypto4"_h: - suffix = "4s, 'Va.4s"; - break; - case "sm3tt1a_vvv4_crypto3_imm2"_h: - case "sm3tt1b_vvv4_crypto3_imm2"_h: - case "sm3tt2a_vvv4_crypto3_imm2"_h: - case "sm3tt2b_vvv_crypto3_imm2"_h: - suffix = "s['u1312]"; - break; - } - - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::DisassembleSHA512(const Instruction *instr) { - const char *form = "'Qd, 'Qn, 'Vm.2d"; - const char *suffix = NULL; - switch (form_hash_) { - case "sha512su1_vvv2_cryptosha512_3"_h: - suffix = ", 'Vm.2d"; - VIXL_FALLTHROUGH(); - case "sha512su0_vv2_cryptosha512_2"_h: - form = "'Vd.2d, 'Vn.2d"; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::DisassembleNEON2RegAddlp(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - - static const NEONFormatMap map_lp_ta = - {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; - NEONFormatDecoder nfd(instr); - nfd.SetFormatMap(0, &map_lp_ta); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegCompare(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, #0"; - NEONFormatDecoder nfd(instr); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegFPCompare(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, #0.0"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap()); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegFPConvert(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - static const NEONFormatMap map_cvt_ta = {{22}, {NF_4S, NF_2D}}; - - static const NEONFormatMap map_cvt_tb = {{22, 30}, - {NF_4H, NF_8H, NF_2S, NF_4S}}; - NEONFormatDecoder nfd(instr, &map_cvt_tb, &map_cvt_ta); - - VectorFormat vform_dst = nfd.GetVectorFormat(0); - switch (form_hash_) { - case "fcvtl_asimdmisc_l"_h: - nfd.SetFormatMaps(&map_cvt_ta, &map_cvt_tb); - break; - case "fcvtxn_asimdmisc_n"_h: - if ((vform_dst != kFormat2S) && (vform_dst != kFormat4S)) { - mnemonic = NULL; - } - break; - } - Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegFP(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPFormatMap()); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegLogical(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); - if (form_hash_ == "not_asimdmisc_r"_h) { - mnemonic = "mvn"; - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON2RegExtract(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - const char *suffix = NULL; - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::IntegerFormatMap(), - NEONFormatDecoder::LongIntegerFormatMap()); - - if (form_hash_ == "shll_asimdmisc_s"_h) { - nfd.SetFormatMaps(nfd.LongIntegerFormatMap(), nfd.IntegerFormatMap()); - switch (instr->GetNEONSize()) { - case 0: - suffix = ", #8"; - break; - case 1: - suffix = ", #16"; - break; - case 2: - suffix = ", #32"; - break; - } - } - Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix); -} - -void Disassembler::VisitNEON2RegMisc(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - NEONFormatDecoder nfd(instr); - - VectorFormat vform_dst = nfd.GetVectorFormat(0); - if (vform_dst != kFormatUndefined) { - uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst); - switch (form_hash_) { - case "cnt_asimdmisc_r"_h: - case "rev16_asimdmisc_r"_h: - if (ls_dst != kBRegSize) { - mnemonic = NULL; - } - break; - case "rev32_asimdmisc_r"_h: - if ((ls_dst == kDRegSize) || (ls_dst == kSRegSize)) { - mnemonic = NULL; - } - break; - case "urecpe_asimdmisc_r"_h: - case "ursqrte_asimdmisc_r"_h: - // For urecpe and ursqrte, only S-sized elements are supported. The MSB - // of the size field is always set by the instruction (0b1x) so we need - // only check and discard D-sized elements here. - VIXL_ASSERT((ls_dst == kSRegSize) || (ls_dst == kDRegSize)); - VIXL_FALLTHROUGH(); - case "clz_asimdmisc_r"_h: - case "cls_asimdmisc_r"_h: - case "rev64_asimdmisc_r"_h: - if (ls_dst == kDRegSize) { - mnemonic = NULL; - } - break; - } - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::VisitNEON2RegMiscFP16(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.'?30:84h, 'Vn.'?30:84h"; - const char *suffix = NULL; - - switch (form_hash_) { - case "fcmeq_asimdmiscfp16_fz"_h: - case "fcmge_asimdmiscfp16_fz"_h: - case "fcmgt_asimdmiscfp16_fz"_h: - case "fcmle_asimdmiscfp16_fz"_h: - case "fcmlt_asimdmiscfp16_fz"_h: - suffix = ", #0.0"; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::DisassembleNEON3SameLogical(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); - - switch (form_hash_) { - case "orr_asimdsame_only"_h: - if (instr->GetRm() == instr->GetRn()) { - mnemonic = "mov"; - form = "'Vd.%s, 'Vn.%s"; - } - break; - case "pmul_asimdsame_only"_h: - if (instr->GetNEONSize() != 0) { - mnemonic = NULL; - } - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEON3SameFHM(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.'?30:42s, 'Vn.'?30:42h, 'Vm.'?30:42h"); -} - -void Disassembler::DisassembleNEON3SameNoD(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - static const NEONFormatMap map = - {{23, 22, 30}, - {NF_8B, NF_16B, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}}; - NEONFormatDecoder nfd(instr, &map); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::VisitNEON3Same(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - NEONFormatDecoder nfd(instr); - - if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) { - nfd.SetFormatMaps(nfd.FPFormatMap()); - } - - VectorFormat vform_dst = nfd.GetVectorFormat(0); - if (vform_dst != kFormatUndefined) { - uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst); - switch (form_hash_) { - case "sqdmulh_asimdsame_only"_h: - case "sqrdmulh_asimdsame_only"_h: - if ((ls_dst == kBRegSize) || (ls_dst == kDRegSize)) { - mnemonic = NULL; - } - break; - } - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::VisitNEON3SameFP16(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - NEONFormatDecoder nfd(instr); - nfd.SetFormatMaps(nfd.FP16FormatMap()); - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::VisitNEON3SameExtra(const Instruction *instr) { - static const NEONFormatMap map_dot = - {{23, 22, 30}, {NF_UNDEF, NF_UNDEF, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S}}; - static const NEONFormatMap map_fc = - {{23, 22, 30}, - {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; - static const NEONFormatMap map_rdm = - {{23, 22, 30}, {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S}}; - - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - const char *suffix = NULL; - - NEONFormatDecoder nfd(instr, &map_fc); - - switch (form_hash_) { - case "fcmla_asimdsame2_c"_h: - suffix = ", #'u1211*90"; - break; - case "fcadd_asimdsame2_c"_h: - // Bit 10 is always set, so this gives 90 * 1 or 3. - suffix = ", #'u1212:1010*90"; - break; - case "sdot_asimdsame2_d"_h: - case "udot_asimdsame2_d"_h: - case "usdot_asimdsame2_d"_h: - nfd.SetFormatMaps(nfd.LogicalFormatMap()); - nfd.SetFormatMap(0, &map_dot); - break; - default: - nfd.SetFormatMaps(&map_rdm); - break; - } - - Format(instr, mnemonic, nfd.Substitute(form), suffix); -} - -void Disassembler::DisassembleNEON4Same(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.16b, 'Vn.16b, 'Vm.16b, 'Va.16b"); -} - -void Disassembler::DisassembleNEONXar(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.2d, 'Vn.2d, 'Vm.2d, #'u1510"); -} - -void Disassembler::DisassembleNEONRax1(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.2d, 'Vn.2d, 'Vm.2d"); -} - -void Disassembler::VisitNEON3Different(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s"; - - NEONFormatDecoder nfd(instr); - nfd.SetFormatMap(0, nfd.LongIntegerFormatMap()); - - switch (form_hash_) { - case "saddw_asimddiff_w"_h: - case "ssubw_asimddiff_w"_h: - case "uaddw_asimddiff_w"_h: - case "usubw_asimddiff_w"_h: - nfd.SetFormatMap(1, nfd.LongIntegerFormatMap()); - break; - case "addhn_asimddiff_n"_h: - case "raddhn_asimddiff_n"_h: - case "rsubhn_asimddiff_n"_h: - case "subhn_asimddiff_n"_h: - nfd.SetFormatMaps(nfd.LongIntegerFormatMap()); - nfd.SetFormatMap(0, nfd.IntegerFormatMap()); - break; - case "sqdmlal_asimddiff_l"_h: - case "sqdmlsl_asimddiff_l"_h: - case "sqdmull_asimddiff_l"_h: - if (nfd.GetVectorFormat(0) == kFormat8H) { - mnemonic = NULL; - } - break; - } - Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONPolynomialMul(const Instruction *instr) { - const char *mnemonic = instr->ExtractBit(30) ? "pmull2" : "pmull"; - const char *form = NULL; - int size = instr->ExtractBits(23, 22); - if (size == 0) { - // Bits 30:27 of the instruction are x001, where x is the Q bit. Map - // this to "8" and "16" by adding 7. - form = "'Vd.8h, 'Vn.'u3127+7b, 'Vm.'u3127+7b"; - } else if (size == 3) { - form = "'Vd.1q, 'Vn.'?30:21d, 'Vm.'?30:21d"; - } else { - mnemonic = NULL; - } - Format(instr, mnemonic, form); -} - -void Disassembler::DisassembleNEONFPAcrossLanes(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Sd, 'Vn.4s"; - if ((instr->GetNEONQ() == 0) || (instr->ExtractBit(22) == 1)) { - mnemonic = NULL; - } - Format(instr, mnemonic, form); -} - -void Disassembler::DisassembleNEONFP16AcrossLanes(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Hd, 'Vn.'?30:84h"); -} - -void Disassembler::VisitNEONAcrossLanes(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, 'Vn.%s"; - - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::ScalarFormatMap(), - NEONFormatDecoder::IntegerFormatMap()); - - switch (form_hash_) { - case "saddlv_asimdall_only"_h: - case "uaddlv_asimdall_only"_h: - nfd.SetFormatMap(0, nfd.LongScalarFormatMap()); - } - - VectorFormat vform_src = nfd.GetVectorFormat(1); - if ((vform_src == kFormat2S) || (vform_src == kFormat2D)) { - mnemonic = NULL; - } - - Format(instr, - mnemonic, - nfd.Substitute(form, - NEONFormatDecoder::kPlaceholder, - NEONFormatDecoder::kFormat)); -} - -void Disassembler::VisitNEONByIndexedElement(const Instruction *instr) { - const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]"; - static const NEONFormatMap map_v = - {{23, 22, 30}, - {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_2S, NF_4S, NF_UNDEF, NF_UNDEF}}; - static const NEONFormatMap map_s = {{23, 22}, - {NF_UNDEF, NF_H, NF_S, NF_UNDEF}}; - NEONFormatDecoder nfd(instr, &map_v, &map_v, &map_s); - Format(instr, mnemonic_.c_str(), nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONMulByElementLong(const Instruction *instr) { - const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]"; - // TODO: Disallow undefined element types for this instruction. - static const NEONFormatMap map_ta = {{23, 22}, {NF_UNDEF, NF_4S, NF_2D}}; - NEONFormatDecoder nfd(instr, - &map_ta, - NEONFormatDecoder::IntegerFormatMap(), - NEONFormatDecoder::ScalarFormatMap()); - Format(instr, nfd.Mnemonic(mnemonic_.c_str()), nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONDotProdByElement(const Instruction *instr) { - const char *form = instr->ExtractBit(30) ? "'Vd.4s, 'Vn.16" : "'Vd.2s, 'Vn.8"; - const char *suffix = "b, 'Vm.4b['u1111:2121]"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::DisassembleNEONFPMulByElement(const Instruction *instr) { - const char *form = "'Vd.%s, 'Vn.%s, 'Vf.%s['IVByElemIndex]"; - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::FPFormatMap(), - NEONFormatDecoder::FPFormatMap(), - NEONFormatDecoder::FPScalarFormatMap()); - Format(instr, mnemonic_.c_str(), nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONHalfFPMulByElement(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "'Vd.'?30:84h, 'Vn.'?30:84h, " - "'Ve.h['IVByElemIndex]"); -} - -void Disassembler::DisassembleNEONFPMulByElementLong(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "'Vd.'?30:42s, 'Vn.'?30:42h, " - "'Ve.h['IVByElemIndexFHM]"); -} - -void Disassembler::DisassembleNEONComplexMulByElement( - const Instruction *instr) { - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s['IVByElemIndexRot], #'u1413*90"; - // TODO: Disallow undefined element types for this instruction. - static const NEONFormatMap map_cn = - {{23, 22, 30}, - {NF_UNDEF, NF_UNDEF, NF_4H, NF_8H, NF_UNDEF, NF_4S, NF_UNDEF, NF_UNDEF}}; - NEONFormatDecoder nfd(instr, - &map_cn, - &map_cn, - NEONFormatDecoder::ScalarFormatMap()); - Format(instr, mnemonic_.c_str(), nfd.Substitute(form)); -} - -void Disassembler::VisitNEONCopy(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "(NEONCopy)"; - - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::TriangularFormatMap(), - NEONFormatDecoder::TriangularScalarFormatMap()); - - switch (form_hash_) { - case "ins_asimdins_iv_v"_h: - mnemonic = "mov"; - nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); - form = "'Vd.%s['IVInsIndex1], 'Vn.%s['IVInsIndex2]"; - break; - case "ins_asimdins_ir_r"_h: - mnemonic = "mov"; - nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); - if (nfd.GetVectorFormat() == kFormatD) { - form = "'Vd.%s['IVInsIndex1], 'Xn"; - } else { - form = "'Vd.%s['IVInsIndex1], 'Wn"; - } - break; - case "umov_asimdins_w_w"_h: - case "umov_asimdins_x_x"_h: - if (instr->Mask(NEON_Q) || ((instr->GetImmNEON5() & 7) == 4)) { - mnemonic = "mov"; - } - nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); - if (nfd.GetVectorFormat() == kFormatD) { - form = "'Xd, 'Vn.%s['IVInsIndex1]"; - } else { - form = "'Wd, 'Vn.%s['IVInsIndex1]"; - } - break; - case "smov_asimdins_w_w"_h: - case "smov_asimdins_x_x"_h: { - nfd.SetFormatMap(0, nfd.TriangularScalarFormatMap()); - VectorFormat vform = nfd.GetVectorFormat(); - if ((vform == kFormatD) || - ((vform == kFormatS) && (instr->ExtractBit(30) == 0))) { - mnemonic = NULL; - } - form = "'R30d, 'Vn.%s['IVInsIndex1]"; - break; - } - case "dup_asimdins_dv_v"_h: - form = "'Vd.%s, 'Vn.%s['IVInsIndex1]"; - break; - case "dup_asimdins_dr_r"_h: - if (nfd.GetVectorFormat() == kFormat2D) { - form = "'Vd.%s, 'Xn"; - } else { - form = "'Vd.%s, 'Wn"; - } - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONExtract(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'Vm.%s, 'IVExtract"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); - if ((instr->GetImmNEONExt() > 7) && (instr->GetNEONQ() == 0)) { - mnemonic = NULL; - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONLoadStoreMultiStruct(const Instruction *instr) { - const char *mnemonic = NULL; - const char *form = NULL; - const char *form_1v = "{'Vt.%1$s}, ['Xns]"; - const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns]"; - const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns]"; - const char *form_4v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); - - switch (instr->Mask(NEONLoadStoreMultiStructMask)) { - case NEON_LD1_1v: - mnemonic = "ld1"; - form = form_1v; - break; - case NEON_LD1_2v: - mnemonic = "ld1"; - form = form_2v; - break; - case NEON_LD1_3v: - mnemonic = "ld1"; - form = form_3v; - break; - case NEON_LD1_4v: - mnemonic = "ld1"; - form = form_4v; - break; - case NEON_LD2: - mnemonic = "ld2"; - form = form_2v; - break; - case NEON_LD3: - mnemonic = "ld3"; - form = form_3v; - break; - case NEON_LD4: - mnemonic = "ld4"; - form = form_4v; - break; - case NEON_ST1_1v: - mnemonic = "st1"; - form = form_1v; - break; - case NEON_ST1_2v: - mnemonic = "st1"; - form = form_2v; - break; - case NEON_ST1_3v: - mnemonic = "st1"; - form = form_3v; - break; - case NEON_ST1_4v: - mnemonic = "st1"; - form = form_4v; - break; - case NEON_ST2: - mnemonic = "st2"; - form = form_2v; - break; - case NEON_ST3: - mnemonic = "st3"; - form = form_3v; - break; - case NEON_ST4: - mnemonic = "st4"; - form = form_4v; - break; - default: - break; - } - - // Work out unallocated encodings. - bool allocated = (mnemonic != NULL); - switch (instr->Mask(NEONLoadStoreMultiStructMask)) { - case NEON_LD2: - case NEON_LD3: - case NEON_LD4: - case NEON_ST2: - case NEON_ST3: - case NEON_ST4: - // LD[2-4] and ST[2-4] cannot use .1d format. - allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3); - break; - default: - break; - } - if (allocated) { - VIXL_ASSERT(mnemonic != NULL); - VIXL_ASSERT(form != NULL); - } else { - mnemonic = "unallocated"; - form = "(NEONLoadStoreMultiStruct)"; - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONLoadStoreMultiStructPostIndex( - const Instruction *instr) { - const char *mnemonic = NULL; - const char *form = NULL; - const char *form_1v = "{'Vt.%1$s}, ['Xns], 'Xmr1"; - const char *form_2v = "{'Vt.%1$s, 'Vt2.%1$s}, ['Xns], 'Xmr2"; - const char *form_3v = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s}, ['Xns], 'Xmr3"; - const char *form_4v = - "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmr4"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); - - switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) { - case NEON_LD1_1v_post: - mnemonic = "ld1"; - form = form_1v; - break; - case NEON_LD1_2v_post: - mnemonic = "ld1"; - form = form_2v; - break; - case NEON_LD1_3v_post: - mnemonic = "ld1"; - form = form_3v; - break; - case NEON_LD1_4v_post: - mnemonic = "ld1"; - form = form_4v; - break; - case NEON_LD2_post: - mnemonic = "ld2"; - form = form_2v; - break; - case NEON_LD3_post: - mnemonic = "ld3"; - form = form_3v; - break; - case NEON_LD4_post: - mnemonic = "ld4"; - form = form_4v; - break; - case NEON_ST1_1v_post: - mnemonic = "st1"; - form = form_1v; - break; - case NEON_ST1_2v_post: - mnemonic = "st1"; - form = form_2v; - break; - case NEON_ST1_3v_post: - mnemonic = "st1"; - form = form_3v; - break; - case NEON_ST1_4v_post: - mnemonic = "st1"; - form = form_4v; - break; - case NEON_ST2_post: - mnemonic = "st2"; - form = form_2v; - break; - case NEON_ST3_post: - mnemonic = "st3"; - form = form_3v; - break; - case NEON_ST4_post: - mnemonic = "st4"; - form = form_4v; - break; - default: - break; - } - - // Work out unallocated encodings. - bool allocated = (mnemonic != NULL); - switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) { - case NEON_LD2_post: - case NEON_LD3_post: - case NEON_LD4_post: - case NEON_ST2_post: - case NEON_ST3_post: - case NEON_ST4_post: - // LD[2-4] and ST[2-4] cannot use .1d format. - allocated = (instr->GetNEONQ() != 0) || (instr->GetNEONLSSize() != 3); - break; - default: - break; - } - if (allocated) { - VIXL_ASSERT(mnemonic != NULL); - VIXL_ASSERT(form != NULL); - } else { - mnemonic = "unallocated"; - form = "(NEONLoadStoreMultiStructPostIndex)"; - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONLoadStoreSingleStruct(const Instruction *instr) { - const char *mnemonic = NULL; - const char *form = NULL; - - const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns]"; - const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns]"; - const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns]"; - const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns]"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); - - switch (instr->Mask(NEONLoadStoreSingleStructMask)) { - case NEON_LD1_b: - mnemonic = "ld1"; - form = form_1b; - break; - case NEON_LD1_h: - mnemonic = "ld1"; - form = form_1h; - break; - case NEON_LD1_s: - mnemonic = "ld1"; - VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d); - form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d; - break; - case NEON_ST1_b: - mnemonic = "st1"; - form = form_1b; - break; - case NEON_ST1_h: - mnemonic = "st1"; - form = form_1h; - break; - case NEON_ST1_s: - mnemonic = "st1"; - VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d); - form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d; - break; - case NEON_LD1R: - mnemonic = "ld1r"; - form = "{'Vt.%s}, ['Xns]"; - break; - case NEON_LD2_b: - case NEON_ST2_b: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns]"; - break; - case NEON_LD2_h: - case NEON_ST2_h: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns]"; - break; - case NEON_LD2_s: - case NEON_ST2_s: - VIXL_STATIC_ASSERT((NEON_ST2_s | (1 << NEONLSSize_offset)) == NEON_ST2_d); - VIXL_STATIC_ASSERT((NEON_LD2_s | (1 << NEONLSSize_offset)) == NEON_LD2_d); - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - if ((instr->GetNEONLSSize() & 1) == 0) { - form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns]"; - } else { - form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns]"; - } - break; - case NEON_LD2R: - mnemonic = "ld2r"; - form = "{'Vt.%s, 'Vt2.%s}, ['Xns]"; - break; - case NEON_LD3_b: - case NEON_ST3_b: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns]"; - break; - case NEON_LD3_h: - case NEON_ST3_h: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns]"; - break; - case NEON_LD3_s: - case NEON_ST3_s: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - if ((instr->GetNEONLSSize() & 1) == 0) { - form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns]"; - } else { - form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns]"; - } - break; - case NEON_LD3R: - mnemonic = "ld3r"; - form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns]"; - break; - case NEON_LD4_b: - case NEON_ST4_b: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4"; - form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns]"; - break; - case NEON_LD4_h: - case NEON_ST4_h: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4"; - form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns]"; - break; - case NEON_LD4_s: - case NEON_ST4_s: - VIXL_STATIC_ASSERT((NEON_LD4_s | (1 << NEONLSSize_offset)) == NEON_LD4_d); - VIXL_STATIC_ASSERT((NEON_ST4_s | (1 << NEONLSSize_offset)) == NEON_ST4_d); - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4"; - if ((instr->GetNEONLSSize() & 1) == 0) { - form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns]"; - } else { - form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns]"; - } - break; - case NEON_LD4R: - mnemonic = "ld4r"; - form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns]"; - break; - default: - break; - } - - // Work out unallocated encodings. - bool allocated = (mnemonic != NULL); - switch (instr->Mask(NEONLoadStoreSingleStructMask)) { - case NEON_LD1_h: - case NEON_LD2_h: - case NEON_LD3_h: - case NEON_LD4_h: - case NEON_ST1_h: - case NEON_ST2_h: - case NEON_ST3_h: - case NEON_ST4_h: - VIXL_ASSERT(allocated); - allocated = ((instr->GetNEONLSSize() & 1) == 0); - break; - case NEON_LD1_s: - case NEON_LD2_s: - case NEON_LD3_s: - case NEON_LD4_s: - case NEON_ST1_s: - case NEON_ST2_s: - case NEON_ST3_s: - case NEON_ST4_s: - VIXL_ASSERT(allocated); - allocated = (instr->GetNEONLSSize() <= 1) && - ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0)); - break; - case NEON_LD1R: - case NEON_LD2R: - case NEON_LD3R: - case NEON_LD4R: - VIXL_ASSERT(allocated); - allocated = (instr->GetNEONS() == 0); - break; - default: - break; - } - if (allocated) { - VIXL_ASSERT(mnemonic != NULL); - VIXL_ASSERT(form != NULL); - } else { - mnemonic = "unallocated"; - form = "(NEONLoadStoreSingleStruct)"; - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONLoadStoreSingleStructPostIndex( - const Instruction *instr) { - const char *mnemonic = NULL; - const char *form = NULL; - - const char *form_1b = "{'Vt.b}['IVLSLane0], ['Xns], 'Xmb1"; - const char *form_1h = "{'Vt.h}['IVLSLane1], ['Xns], 'Xmb2"; - const char *form_1s = "{'Vt.s}['IVLSLane2], ['Xns], 'Xmb4"; - const char *form_1d = "{'Vt.d}['IVLSLane3], ['Xns], 'Xmb8"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); - - switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) { - case NEON_LD1_b_post: - mnemonic = "ld1"; - form = form_1b; - break; - case NEON_LD1_h_post: - mnemonic = "ld1"; - form = form_1h; - break; - case NEON_LD1_s_post: - mnemonic = "ld1"; - VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d); - form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d; - break; - case NEON_ST1_b_post: - mnemonic = "st1"; - form = form_1b; - break; - case NEON_ST1_h_post: - mnemonic = "st1"; - form = form_1h; - break; - case NEON_ST1_s_post: - mnemonic = "st1"; - VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d); - form = ((instr->GetNEONLSSize() & 1) == 0) ? form_1s : form_1d; - break; - case NEON_LD1R_post: - mnemonic = "ld1r"; - form = "{'Vt.%s}, ['Xns], 'Xmz1"; - break; - case NEON_LD2_b_post: - case NEON_ST2_b_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - form = "{'Vt.b, 'Vt2.b}['IVLSLane0], ['Xns], 'Xmb2"; - break; - case NEON_ST2_h_post: - case NEON_LD2_h_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - form = "{'Vt.h, 'Vt2.h}['IVLSLane1], ['Xns], 'Xmb4"; - break; - case NEON_LD2_s_post: - case NEON_ST2_s_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld2" : "st2"; - if ((instr->GetNEONLSSize() & 1) == 0) - form = "{'Vt.s, 'Vt2.s}['IVLSLane2], ['Xns], 'Xmb8"; - else - form = "{'Vt.d, 'Vt2.d}['IVLSLane3], ['Xns], 'Xmb16"; - break; - case NEON_LD2R_post: - mnemonic = "ld2r"; - form = "{'Vt.%s, 'Vt2.%s}, ['Xns], 'Xmz2"; - break; - case NEON_LD3_b_post: - case NEON_ST3_b_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - form = "{'Vt.b, 'Vt2.b, 'Vt3.b}['IVLSLane0], ['Xns], 'Xmb3"; - break; - case NEON_LD3_h_post: - case NEON_ST3_h_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - form = "{'Vt.h, 'Vt2.h, 'Vt3.h}['IVLSLane1], ['Xns], 'Xmb6"; - break; - case NEON_LD3_s_post: - case NEON_ST3_s_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld3" : "st3"; - if ((instr->GetNEONLSSize() & 1) == 0) - form = "{'Vt.s, 'Vt2.s, 'Vt3.s}['IVLSLane2], ['Xns], 'Xmb12"; - else - form = "{'Vt.d, 'Vt2.d, 'Vt3.d}['IVLSLane3], ['Xns], 'Xmb24"; - break; - case NEON_LD3R_post: - mnemonic = "ld3r"; - form = "{'Vt.%s, 'Vt2.%s, 'Vt3.%s}, ['Xns], 'Xmz3"; - break; - case NEON_LD4_b_post: - case NEON_ST4_b_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4"; - form = "{'Vt.b, 'Vt2.b, 'Vt3.b, 'Vt4.b}['IVLSLane0], ['Xns], 'Xmb4"; - break; - case NEON_LD4_h_post: - case NEON_ST4_h_post: - mnemonic = (instr->GetLdStXLoad()) == 1 ? "ld4" : "st4"; - form = "{'Vt.h, 'Vt2.h, 'Vt3.h, 'Vt4.h}['IVLSLane1], ['Xns], 'Xmb8"; - break; - case NEON_LD4_s_post: - case NEON_ST4_s_post: - mnemonic = (instr->GetLdStXLoad() == 1) ? "ld4" : "st4"; - if ((instr->GetNEONLSSize() & 1) == 0) - form = "{'Vt.s, 'Vt2.s, 'Vt3.s, 'Vt4.s}['IVLSLane2], ['Xns], 'Xmb16"; - else - form = "{'Vt.d, 'Vt2.d, 'Vt3.d, 'Vt4.d}['IVLSLane3], ['Xns], 'Xmb32"; - break; - case NEON_LD4R_post: - mnemonic = "ld4r"; - form = "{'Vt.%1$s, 'Vt2.%1$s, 'Vt3.%1$s, 'Vt4.%1$s}, ['Xns], 'Xmz4"; - break; - default: - break; - } - - // Work out unallocated encodings. - bool allocated = (mnemonic != NULL); - switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) { - case NEON_LD1_h_post: - case NEON_LD2_h_post: - case NEON_LD3_h_post: - case NEON_LD4_h_post: - case NEON_ST1_h_post: - case NEON_ST2_h_post: - case NEON_ST3_h_post: - case NEON_ST4_h_post: - VIXL_ASSERT(allocated); - allocated = ((instr->GetNEONLSSize() & 1) == 0); - break; - case NEON_LD1_s_post: - case NEON_LD2_s_post: - case NEON_LD3_s_post: - case NEON_LD4_s_post: - case NEON_ST1_s_post: - case NEON_ST2_s_post: - case NEON_ST3_s_post: - case NEON_ST4_s_post: - VIXL_ASSERT(allocated); - allocated = (instr->GetNEONLSSize() <= 1) && - ((instr->GetNEONLSSize() == 0) || (instr->GetNEONS() == 0)); - break; - case NEON_LD1R_post: - case NEON_LD2R_post: - case NEON_LD3R_post: - case NEON_LD4R_post: - VIXL_ASSERT(allocated); - allocated = (instr->GetNEONS() == 0); - break; - default: - break; - } - if (allocated) { - VIXL_ASSERT(mnemonic != NULL); - VIXL_ASSERT(form != NULL); - } else { - mnemonic = "unallocated"; - form = "(NEONLoadStoreSingleStructPostIndex)"; - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONModifiedImmediate(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vt.%s, 'IVMIImm8, lsl 'IVMIShiftAmt1"; - - static const NEONFormatMap map_h = {{30}, {NF_4H, NF_8H}}; - static const NEONFormatMap map_s = {{30}, {NF_2S, NF_4S}}; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); - - switch (form_hash_) { - case "movi_asimdimm_n_b"_h: - form = "'Vt.%s, 'IVMIImm8"; - break; - case "bic_asimdimm_l_hl"_h: - case "movi_asimdimm_l_hl"_h: - case "mvni_asimdimm_l_hl"_h: - case "orr_asimdimm_l_hl"_h: - nfd.SetFormatMap(0, &map_h); - break; - case "movi_asimdimm_m_sm"_h: - case "mvni_asimdimm_m_sm"_h: - form = "'Vt.%s, 'IVMIImm8, msl 'IVMIShiftAmt2"; - VIXL_FALLTHROUGH(); - case "bic_asimdimm_l_sl"_h: - case "movi_asimdimm_l_sl"_h: - case "mvni_asimdimm_l_sl"_h: - case "orr_asimdimm_l_sl"_h: - nfd.SetFormatMap(0, &map_s); - break; - case "movi_asimdimm_d_ds"_h: - form = "'Dd, 'IVMIImm"; - break; - case "movi_asimdimm_d2_d"_h: - form = "'Vt.2d, 'IVMIImm"; - break; - case "fmov_asimdimm_h_h"_h: - form = "'Vt.%s, 'IFPNeon"; - nfd.SetFormatMap(0, &map_h); - break; - case "fmov_asimdimm_s_s"_h: - form = "'Vt.%s, 'IFPNeon"; - nfd.SetFormatMap(0, &map_s); - break; - case "fmov_asimdimm_d2_d"_h: - form = "'Vt.2d, 'IFPNeon"; - break; - } - - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONScalar2RegMiscOnlyD( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Dd, 'Dn"; - const char *suffix = ", #0"; - if (instr->GetNEONSize() != 3) { - mnemonic = NULL; - } - switch (form_hash_) { - case "abs_asisdmisc_r"_h: - case "neg_asisdmisc_r"_h: - suffix = NULL; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::DisassembleNEONFPScalar2RegMisc(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn"; - const char *suffix = NULL; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap()); - switch (form_hash_) { - case "fcmeq_asisdmisc_fz"_h: - case "fcmge_asisdmisc_fz"_h: - case "fcmgt_asisdmisc_fz"_h: - case "fcmle_asisdmisc_fz"_h: - case "fcmlt_asisdmisc_fz"_h: - suffix = ", #0.0"; - break; - case "fcvtxn_asisdmisc_n"_h: - if (nfd.GetVectorFormat(0) == kFormatS) { // Source format. - mnemonic = NULL; - } - form = "'Sd, 'Dn"; - } - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix); -} - -void Disassembler::VisitNEONScalar2RegMisc(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); - switch (form_hash_) { - case "sqxtn_asisdmisc_n"_h: - case "sqxtun_asisdmisc_n"_h: - case "uqxtn_asisdmisc_n"_h: - nfd.SetFormatMap(1, nfd.LongScalarFormatMap()); - } - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); -} - -void Disassembler::VisitNEONScalar2RegMiscFP16(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Hd, 'Hn"; - const char *suffix = NULL; - - switch (form_hash_) { - case "fcmeq_asisdmiscfp16_fz"_h: - case "fcmge_asisdmiscfp16_fz"_h: - case "fcmgt_asisdmiscfp16_fz"_h: - case "fcmle_asisdmiscfp16_fz"_h: - case "fcmlt_asisdmiscfp16_fz"_h: - suffix = ", #0.0"; - } - Format(instr, mnemonic, form, suffix); -} - - -void Disassembler::VisitNEONScalar3Diff(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, %sm"; - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::LongScalarFormatMap(), - NEONFormatDecoder::ScalarFormatMap()); - if (nfd.GetVectorFormat(0) == kFormatH) { - mnemonic = NULL; - } - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); -} - -void Disassembler::DisassembleNEONFPScalar3Same(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, %sm"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap()); - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); -} - -void Disassembler::DisassembleNEONScalar3SameOnlyD(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Dd, 'Dn, 'Dm"; - if (instr->GetNEONSize() != 3) { - mnemonic = NULL; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitNEONScalar3Same(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, %sm"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); - VectorFormat vform = nfd.GetVectorFormat(0); - switch (form_hash_) { - case "srshl_asisdsame_only"_h: - case "urshl_asisdsame_only"_h: - case "sshl_asisdsame_only"_h: - case "ushl_asisdsame_only"_h: - if (vform != kFormatD) { - mnemonic = NULL; - } - break; - case "sqdmulh_asisdsame_only"_h: - case "sqrdmulh_asisdsame_only"_h: - case "sqrdmlah_asisdsame2_only"_h: - case "sqrdmlsh_asisdsame2_only"_h: - if ((vform == kFormatB) || (vform == kFormatD)) { - mnemonic = NULL; - } - } - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); -} - -void Disassembler::VisitNEONScalar3SameFP16(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Hd, 'Hn, 'Hm"); -} - -void Disassembler::VisitNEONScalar3SameExtra(const Instruction *instr) { - USE(instr); - // Nothing to do - handled by VisitNEONScalar3Same. - VIXL_UNREACHABLE(); -} - -void Disassembler::DisassembleNEONScalarSatMulLongIndex( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]"; - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::LongScalarFormatMap(), - NEONFormatDecoder::ScalarFormatMap()); - if (nfd.GetVectorFormat(0) == kFormatH) { - mnemonic = NULL; - } - Format(instr, - mnemonic, - nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat)); -} - -void Disassembler::DisassembleNEONFPScalarMulIndex(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]"; - static const NEONFormatMap map = {{23, 22}, {NF_H, NF_UNDEF, NF_S, NF_D}}; - NEONFormatDecoder nfd(instr, &map); - Format(instr, - mnemonic, - nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat)); -} - -void Disassembler::VisitNEONScalarByIndexedElement(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, 'Vf.%s['IVByElemIndex]"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); - VectorFormat vform_dst = nfd.GetVectorFormat(0); - if ((vform_dst == kFormatB) || (vform_dst == kFormatD)) { - mnemonic = NULL; - } - Format(instr, - mnemonic, - nfd.Substitute(form, nfd.kPlaceholder, nfd.kPlaceholder, nfd.kFormat)); -} - - -void Disassembler::VisitNEONScalarCopy(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(NEONScalarCopy)"; - - NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap()); - - if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) { - mnemonic = "mov"; - form = "%sd, 'Vn.%s['IVInsIndex1]"; - } - - Format(instr, mnemonic, nfd.Substitute(form, nfd.kPlaceholder, nfd.kFormat)); -} - - -void Disassembler::VisitNEONScalarPairwise(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - if (form_hash_ == "addp_asisdpair_only"_h) { - // All pairwise operations except ADDP use bit U to differentiate FP16 - // from FP32/FP64 variations. - if (instr->GetNEONSize() != 3) { - mnemonic = NULL; - } - Format(instr, mnemonic, "'Dd, 'Vn.2d"); - } else { - const char *form = "%sd, 'Vn.2%s"; - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::FPScalarPairwiseFormatMap()); - - Format(instr, - mnemonic, - nfd.Substitute(form, - NEONFormatDecoder::kPlaceholder, - NEONFormatDecoder::kFormat)); - } -} - -void Disassembler::DisassembleNEONScalarShiftImmOnlyD( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Dd, 'Dn, "; - const char *suffix = "'IsR"; - - if (instr->ExtractBit(22) == 0) { - // Only D registers are supported. - mnemonic = NULL; - } - - switch (form_hash_) { - case "shl_asisdshf_r"_h: - case "sli_asisdshf_r"_h: - suffix = "'IsL"; - } - - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::DisassembleNEONScalarShiftRightNarrowImm( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, 'IsR"; - static const NEONFormatMap map_dst = - {{22, 21, 20, 19}, {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S}}; - static const NEONFormatMap map_src = - {{22, 21, 20, 19}, {NF_UNDEF, NF_H, NF_S, NF_S, NF_D, NF_D, NF_D, NF_D}}; - NEONFormatDecoder nfd(instr, &map_dst, &map_src); - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form)); -} - -void Disassembler::VisitNEONScalarShiftImmediate(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "%sd, %sn, "; - const char *suffix = "'IsR"; - - // clang-format off - static const NEONFormatMap map = {{22, 21, 20, 19}, - {NF_UNDEF, NF_B, NF_H, NF_H, - NF_S, NF_S, NF_S, NF_S, - NF_D, NF_D, NF_D, NF_D, - NF_D, NF_D, NF_D, NF_D}}; - // clang-format on - NEONFormatDecoder nfd(instr, &map); - switch (form_hash_) { - case "sqshlu_asisdshf_r"_h: - case "sqshl_asisdshf_r"_h: - case "uqshl_asisdshf_r"_h: - suffix = "'IsL"; - break; - default: - if (nfd.GetVectorFormat(0) == kFormatB) { - mnemonic = NULL; - } - } - Format(instr, mnemonic, nfd.SubstitutePlaceholders(form), suffix); -} - -void Disassembler::DisassembleNEONShiftLeftLongImm(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s"; - const char *suffix = ", 'IsL"; - - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::ShiftLongNarrowImmFormatMap(), - NEONFormatDecoder::ShiftImmFormatMap()); - - if (instr->GetImmNEONImmb() == 0 && - CountSetBits(instr->GetImmNEONImmh(), 32) == 1) { // xtl variant. - VIXL_ASSERT((form_hash_ == "sshll_asimdshf_l"_h) || - (form_hash_ == "ushll_asimdshf_l"_h)); - mnemonic = (form_hash_ == "sshll_asimdshf_l"_h) ? "sxtl" : "uxtl"; - suffix = NULL; - } - Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form), suffix); -} - -void Disassembler::DisassembleNEONShiftRightImm(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'IsR"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap()); - - VectorFormat vform_dst = nfd.GetVectorFormat(0); - if (vform_dst != kFormatUndefined) { - uint32_t ls_dst = LaneSizeInBitsFromFormat(vform_dst); - switch (form_hash_) { - case "scvtf_asimdshf_c"_h: - case "ucvtf_asimdshf_c"_h: - case "fcvtzs_asimdshf_c"_h: - case "fcvtzu_asimdshf_c"_h: - if (ls_dst == kBRegSize) { - mnemonic = NULL; - } - break; - } - } - Format(instr, mnemonic, nfd.Substitute(form)); -} - -void Disassembler::DisassembleNEONShiftRightNarrowImm( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'IsR"; - - NEONFormatDecoder nfd(instr, - NEONFormatDecoder::ShiftImmFormatMap(), - NEONFormatDecoder::ShiftLongNarrowImmFormatMap()); - Format(instr, nfd.Mnemonic(mnemonic), nfd.Substitute(form)); -} - -void Disassembler::VisitNEONShiftImmediate(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Vd.%s, 'Vn.%s, 'IsL"; - NEONFormatDecoder nfd(instr, NEONFormatDecoder::ShiftImmFormatMap()); - Format(instr, mnemonic, nfd.Substitute(form)); -} - - -void Disassembler::VisitNEONTable(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char form_1v[] = "'Vd.%%s, {'Vn.16b}, 'Vm.%%s"; - const char form_2v[] = "'Vd.%%s, {'Vn.16b, v%d.16b}, 'Vm.%%s"; - const char form_3v[] = "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b}, 'Vm.%%s"; - const char form_4v[] = - "'Vd.%%s, {'Vn.16b, v%d.16b, v%d.16b, v%d.16b}, 'Vm.%%s"; - const char *form = form_1v; - - NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); - - switch (form_hash_) { - case "tbl_asimdtbl_l2_2"_h: - case "tbx_asimdtbl_l2_2"_h: - form = form_2v; - break; - case "tbl_asimdtbl_l3_3"_h: - case "tbx_asimdtbl_l3_3"_h: - form = form_3v; - break; - case "tbl_asimdtbl_l4_4"_h: - case "tbx_asimdtbl_l4_4"_h: - form = form_4v; - break; - } - VIXL_ASSERT(form != NULL); - - char re_form[sizeof(form_4v) + 6]; // 3 * two-digit substitutions => 6 - int reg_num = instr->GetRn(); - snprintf(re_form, - sizeof(re_form), - form, - (reg_num + 1) % kNumberOfVRegisters, - (reg_num + 2) % kNumberOfVRegisters, - (reg_num + 3) % kNumberOfVRegisters); - - Format(instr, mnemonic, nfd.Substitute(re_form)); -} - - -void Disassembler::VisitNEONPerm(const Instruction *instr) { - NEONFormatDecoder nfd(instr); - FormatWithDecodedMnemonic(instr, nfd.Substitute("'Vd.%s, 'Vn.%s, 'Vm.%s")); -} - -void Disassembler::Disassemble_Vd4S_Vn16B_Vm16B(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Vd.4s, 'Vn.16b, 'Vm.16b"); -} - -void Disassembler:: - VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #1]"); -} - -void Disassembler::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw #2]"); -} - -void Disassembler::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.s}, 'Pgl/z, ['Xns, 'Zm.s, '?22:suxtw]"); -} - -void Disassembler::VisitSVE32BitGatherLoad_VectorPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s]"; - const char *form_imm = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016]"; - const char *form_imm_h = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*2]"; - const char *form_imm_w = "{'Zt.s}, 'Pgl/z, ['Zn.s, #'u2016*4]"; - - const char *mnemonic = mnemonic_.c_str(); - switch (form_hash_) { - case "ld1h_z_p_ai_s"_h: - case "ld1sh_z_p_ai_s"_h: - case "ldff1h_z_p_ai_s"_h: - case "ldff1sh_z_p_ai_s"_h: - form_imm = form_imm_h; - break; - case "ld1w_z_p_ai_s"_h: - case "ldff1w_z_p_ai_s"_h: - form_imm = form_imm_w; - break; - } - if (instr->ExtractBits(20, 16) != 0) form = form_imm; - - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.s, '?22:suxtw"; - const char *suffix = NULL; - - switch ( - instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) { - case PRFB_i_p_bz_s_x32_scaled: - mnemonic = "prfb"; - suffix = "]"; - break; - case PRFD_i_p_bz_s_x32_scaled: - mnemonic = "prfd"; - suffix = " #3]"; - break; - case PRFH_i_p_bz_s_x32_scaled: - mnemonic = "prfh"; - suffix = " #1]"; - break; - case PRFW_i_p_bz_s_x32_scaled: - mnemonic = "prfw"; - suffix = " #2]"; - break; - default: - form = "(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets)"; - break; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVE32BitGatherPrefetch_VectorPlusImm( - const Instruction *instr) { - const char *form = (instr->ExtractBits(20, 16) != 0) - ? "'prefSVEOp, 'Pgl, ['Zn.s, #'u2016]" - : "'prefSVEOp, 'Pgl, ['Zn.s]"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw #'u2423]"); -} - -void Disassembler::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "{'Zt.s}, 'Pgl, ['Xns, 'Zm.s, '?14:suxtw]"); -} - -void Disassembler::VisitSVE32BitScatterStore_VectorPlusImm( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "{'Zt.s}, 'Pgl, ['Zn.s"; - const char *suffix = NULL; - - bool is_zero = instr->ExtractBits(20, 16) == 0; - - switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) { - case ST1B_z_p_ai_s: - mnemonic = "st1b"; - suffix = is_zero ? "]" : ", #'u2016]"; - break; - case ST1H_z_p_ai_s: - mnemonic = "st1h"; - suffix = is_zero ? "]" : ", #'u2016*2]"; - break; - case ST1W_z_p_ai_s: - mnemonic = "st1w"; - suffix = is_zero ? "]" : ", #'u2016*4]"; - break; - default: - form = "(SVE32BitScatterStore_VectorPlusImm)"; - break; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw " - "#'u2423]"); -} - -void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, lsl #'u2423]"); -} - -void Disassembler::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d]"); -} - -void Disassembler:: - VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.d}, 'Pgl/z, ['Xns, 'Zm.d, '?22:suxtw]"); -} - -void Disassembler::VisitSVE64BitGatherLoad_VectorPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d]"; - const char *form_imm[4] = {"{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016]", - "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*2]", - "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*4]", - "{'Zt.d}, 'Pgl/z, ['Zn.d, #'u2016*8]"}; - - if (instr->ExtractBits(20, 16) != 0) { - unsigned msz = instr->ExtractBits(24, 23); - bool sign_extend = instr->ExtractBit(14) == 0; - if ((msz == kDRegSizeInBytesLog2) && sign_extend) { - form = "(SVE64BitGatherLoad_VectorPlusImm)"; - } else { - VIXL_ASSERT(msz < ArrayLength(form_imm)); - form = form_imm[msz]; - } - } - - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets( - const Instruction *instr) { - const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d"; - const char *suffix = "]"; - - switch (form_hash_) { - case "prfh_i_p_bz_d_64_scaled"_h: - suffix = ", lsl #1]"; - break; - case "prfs_i_p_bz_d_64_scaled"_h: - suffix = ", lsl #2]"; - break; - case "prfd_i_p_bz_d_64_scaled"_h: - suffix = ", lsl #3]"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler:: - VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets( - const Instruction *instr) { - const char *form = "'prefSVEOp, 'Pgl, ['Xns, 'Zm.d, '?22:suxtw "; - const char *suffix = "]"; - - switch (form_hash_) { - case "prfh_i_p_bz_d_x32_scaled"_h: - suffix = "#1]"; - break; - case "prfs_i_p_bz_d_x32_scaled"_h: - suffix = "#2]"; - break; - case "prfd_i_p_bz_d_x32_scaled"_h: - suffix = "#3]"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVE64BitGatherPrefetch_VectorPlusImm( - const Instruction *instr) { - const char *form = (instr->ExtractBits(20, 16) != 0) - ? "'prefSVEOp, 'Pgl, ['Zn.d, #'u2016]" - : "'prefSVEOp, 'Pgl, ['Zn.d]"; - - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, lsl #'u2423]"); -} - -void Disassembler::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d]"); -} - -void Disassembler:: - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, - "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw #'u2423]"); -} - -void Disassembler:: - VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "{'Zt.d}, 'Pgl, ['Xns, 'Zm.d, '?14:suxtw]"); -} - -void Disassembler::VisitSVE64BitScatterStore_VectorPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.d}, 'Pgl, ['Zn.d"; - const char *suffix = "]"; - - if (instr->ExtractBits(20, 16) != 0) { - switch (form_hash_) { - case "st1b_z_p_ai_d"_h: - suffix = ", #'u2016]"; - break; - case "st1h_z_p_ai_d"_h: - suffix = ", #'u2016*2]"; - break; - case "st1w_z_p_ai_d"_h: - suffix = ", #'u2016*4]"; - break; - case "st1d_z_p_ai_d"_h: - suffix = ", #'u2016*8]"; - break; - } - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEBitwiseLogicalWithImm_Unpredicated( - const Instruction *instr) { - if (instr->GetSVEImmLogical() == 0) { - // The immediate encoded in the instruction is not in the expected format. - Format(instr, "unallocated", "(SVEBitwiseImm)"); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'tl, 'Zd.'tl, 'ITriSvel"); - } -} - -void Disassembler::VisitSVEBitwiseLogical_Predicated(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEBitwiseShiftByImm_Predicated( - const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Zd.'tszp, 'Pgl/m, 'Zd.'tszp, "; - const char *suffix = NULL; - unsigned tsize = (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(9, 8); - - if (tsize == 0) { - mnemonic = "unimplemented"; - form = "(SVEBitwiseShiftByImm_Predicated)"; - } else { - switch (form_hash_) { - case "lsl_z_p_zi"_h: - case "sqshl_z_p_zi"_h: - case "sqshlu_z_p_zi"_h: - case "uqshl_z_p_zi"_h: - suffix = "'ITriSvep"; - break; - case "asrd_z_p_zi"_h: - case "asr_z_p_zi"_h: - case "lsr_z_p_zi"_h: - case "srshr_z_p_zi"_h: - case "urshr_z_p_zi"_h: - suffix = "'ITriSveq"; - break; - default: - mnemonic = "unimplemented"; - form = "(SVEBitwiseShiftByImm_Predicated)"; - break; - } - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVEBitwiseShiftByVector_Predicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEBitwiseShiftByWideElements_Predicated( - const Instruction *instr) { - if (instr->GetSVESize() == kDRegSizeInBytesLog2) { - Format(instr, "unallocated", "(SVEBitwiseShiftByWideElements_Predicated)"); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.d"); - } -} - static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) { VIXL_ASSERT(IsUintN(8 << lane_bytes_log2, value)); @@ -4012,54 +3353,40 @@ static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) { } if ((value & 0xff) == 0) { - // Check for 16-bit patterns. Set least-significant 16 bits, to make tests - // easier; we already checked least-significant byte is zero above. - uint64_t generic_value = value | 0xffff; - - // Check 0x00000000_0000pq00 or 0xffffffff_ffffpq00. - if ((generic_value == 0xffff) || (generic_value == UINT64_MAX)) { + // mov z.d, #signed_16bit_imm + if (value == SignExtend(value, 16)) { return false; } - // Check 0x0000pq00_0000pq00 or 0xffffpq00_ffffpq00. - if (AllWordsMatch(value)) { - generic_value &= 0xffffffff; - if ((generic_value == 0xffff) || (generic_value == UINT32_MAX)) { - return false; - } + // mov z.s, #signed_16bit_imm + uint32_t value32 = static_cast(value); + if (AllWordsMatch(value) && (value32 == SignExtend(value32, 16))) { + return false; } - // Check 0xpq00pq00_pq00pq00. + // mov z.h, #signed_16bit_imm if (AllHalfwordsMatch(value)) { return false; } } else { - // Check for 8-bit patterns. Set least-significant byte, to make tests - // easier. - uint64_t generic_value = value | 0xff; - - // Check 0x00000000_000000pq or 0xffffffff_ffffffpq. - if ((generic_value == 0xff) || (generic_value == UINT64_MAX)) { + // mov z.d, #signed_8bit_imm + if (value == SignExtend(value, 8)) { return false; } - // Check 0x000000pq_000000pq or 0xffffffpq_ffffffpq. - if (AllWordsMatch(value)) { - generic_value &= 0xffffffff; - if ((generic_value == 0xff) || (generic_value == UINT32_MAX)) { - return false; - } + // mov z.s, #signed_8bit_imm + uint32_t value32 = static_cast(value); + if (AllWordsMatch(value) && (value32 == SignExtend(value32, 8))) { + return false; } - // Check 0x00pq00pq_00pq00pq or 0xffpqffpq_ffpqffpq. - if (AllHalfwordsMatch(value)) { - generic_value &= 0xffff; - if ((generic_value == 0xff) || (generic_value == UINT16_MAX)) { - return false; - } + // mov z.h, #signed_8bit_imm + uint16_t value16 = static_cast(value); + if (AllHalfwordsMatch(value) && (value16 == SignExtend(value16, 8))) { + return false; } - // Check 0xpqpqpqpq_pqpqpqpq. + // mov z.b, #signed_8bit_imm if (AllBytesMatch(value)) { return false; } @@ -4068,1615 +3395,63 @@ static bool SVEMoveMaskPreferred(uint64_t value, int lane_bytes_log2) { } void Disassembler::VisitSVEBroadcastBitmaskImm(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBroadcastBitmaskImm)"; - - switch (instr->Mask(SVEBroadcastBitmaskImmMask)) { - case DUPM_z_i: { - uint64_t imm = instr->GetSVEImmLogical(); - if (imm != 0) { - int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2(); - mnemonic = SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm"; - form = "'Zd.'tl, 'ITriSvel"; - } - break; - } - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEBroadcastFPImm_Unpredicated( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBroadcastFPImm_Unpredicated)"; - - if (instr->GetSVEVectorFormat() != kFormatVnB) { - switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) { - case FDUP_z_i: - // The preferred disassembly for fdup is "fmov". - mnemonic = "fmov"; - form = "'Zd.'t, 'IFPSve"; - break; - default: - break; - } - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEBroadcastGeneralRegister(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBroadcastGeneralRegister)"; - - switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) { - case DUP_z_r: - // The preferred disassembly for dup is "mov". - mnemonic = "mov"; - if (instr->GetSVESize() == kDRegSizeInBytesLog2) { - form = "'Zd.'t, 'Xns"; - } else { - form = "'Zd.'t, 'Wns"; - } - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEBroadcastIndexElement(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBroadcastIndexElement)"; - - switch (instr->Mask(SVEBroadcastIndexElementMask)) { - case DUP_z_zi: { - // The tsz field must not be zero. - int tsz = instr->ExtractBits(20, 16); - if (tsz != 0) { - // The preferred disassembly for dup is "mov". - mnemonic = "mov"; - int imm2 = instr->ExtractBits(23, 22); - if ((CountSetBits(imm2) + CountSetBits(tsz)) == 1) { - // If imm2:tsz has one set bit, the index is zero. This is - // disassembled as a mov from a b/h/s/d/q scalar register. - form = "'Zd.'ti, 'ti'u0905"; - } else { - form = "'Zd.'ti, 'Zn.'ti['IVInsSVEIndex]"; - } - } - break; - } - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEBroadcastIntImm_Unpredicated( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBroadcastIntImm_Unpredicated)"; - - switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) { - case DUP_z_i: - // The encoding of byte-sized lanes with lsl #8 is undefined. - if ((instr->GetSVEVectorFormat() == kFormatVnB) && - (instr->ExtractBit(13) == 1)) - break; - - // The preferred disassembly for dup is "mov". - mnemonic = "mov"; - form = (instr->ExtractBit(13) == 0) ? "'Zd.'t, #'s1205" - : "'Zd.'t, #'s1205, lsl #8"; - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVECompressActiveElements(const Instruction *instr) { - // The top bit of size is always set for compact, so 't can only be - // substituted with types S and D. - if (instr->ExtractBit(23) == 1) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zn.'t"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEConditionallyBroadcastElementToVector( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEConditionallyExtractElementToGeneralRegister( - const Instruction *instr) { - const char *form = "'Wd, 'Pgl, 'Wd, 'Zn.'t"; - - if (instr->GetSVESize() == kDRegSizeInBytesLog2) { - form = "'Xd, p'u1210, 'Xd, 'Zn.'t"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEConditionallyExtractElementToSIMDFPScalar( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t"); -} - -void Disassembler::VisitSVEConditionallyTerminateScalars( - const Instruction *instr) { - const char *form = (instr->ExtractBit(22) == 0) ? "'Wn, 'Wm" : "'Xn, 'Xm"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEConstructivePrefix_Unpredicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd, 'Zn"); -} - -void Disassembler::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns"; - const char *suffix = "]"; - - if (instr->GetRm() != kZeroRegCode) { - switch (form_hash_) { - case "ldff1b_z_p_br_u8"_h: - case "ldff1b_z_p_br_u16"_h: - case "ldff1b_z_p_br_u32"_h: - case "ldff1b_z_p_br_u64"_h: - case "ldff1sb_z_p_br_s16"_h: - case "ldff1sb_z_p_br_s32"_h: - case "ldff1sb_z_p_br_s64"_h: - suffix = ", 'Xm]"; - break; - case "ldff1h_z_p_br_u16"_h: - case "ldff1h_z_p_br_u32"_h: - case "ldff1h_z_p_br_u64"_h: - case "ldff1sh_z_p_br_s32"_h: - case "ldff1sh_z_p_br_s64"_h: - suffix = ", 'Xm, lsl #1]"; - break; - case "ldff1w_z_p_br_u32"_h: - case "ldff1w_z_p_br_u64"_h: - case "ldff1sw_z_p_br_s64"_h: - suffix = ", 'Xm, lsl #2]"; - break; - case "ldff1d_z_p_br_u64"_h: - suffix = ", 'Xm, lsl #3]"; - break; - } - } - - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEContiguousNonFaultLoad_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns"; - const char *suffix = - (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]"; - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.b}, 'Pgl/z, ['Xns"; - const char *suffix = - (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]"; - switch (form_hash_) { - case "ldnt1d_z_p_bi_contiguous"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns"; - break; - case "ldnt1h_z_p_bi_contiguous"_h: - form = "{'Zt.h}, 'Pgl/z, ['Xns"; - break; - case "ldnt1w_z_p_bi_contiguous"_h: - form = "{'Zt.s}, 'Pgl/z, ['Xns"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.b}, 'Pgl/z, ['Xns, 'Rm]"; - switch (form_hash_) { - case "ldnt1d_z_p_br_contiguous"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns, 'Rm, lsl #3]"; - break; - case "ldnt1h_z_p_br_contiguous"_h: - form = "{'Zt.h}, 'Pgl/z, ['Xns, 'Rm, lsl #1]"; - break; - case "ldnt1w_z_p_br_contiguous"_h: - form = "{'Zt.s}, 'Pgl/z, ['Xns, 'Rm, lsl #2]"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.b}, 'Pgl, ['Xns"; - const char *suffix = - (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]"; - - switch (form_hash_) { - case "stnt1d_z_p_bi_contiguous"_h: - form = "{'Zt.d}, 'Pgl, ['Xns"; - break; - case "stnt1h_z_p_bi_contiguous"_h: - form = "{'Zt.h}, 'Pgl, ['Xns"; - break; - case "stnt1w_z_p_bi_contiguous"_h: - form = "{'Zt.s}, 'Pgl, ['Xns"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEContiguousNonTemporalStore_ScalarPlusScalar)"; - - switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) { - case STNT1B_z_p_br_contiguous: - mnemonic = "stnt1b"; - form = "{'Zt.b}, 'Pgl, ['Xns, 'Rm]"; - break; - case STNT1D_z_p_br_contiguous: - mnemonic = "stnt1d"; - form = "{'Zt.d}, 'Pgl, ['Xns, 'Rm, lsl #3]"; - break; - case STNT1H_z_p_br_contiguous: - mnemonic = "stnt1h"; - form = "{'Zt.h}, 'Pgl, ['Xns, 'Rm, lsl #1]"; - break; - case STNT1W_z_p_br_contiguous: - mnemonic = "stnt1w"; - form = "{'Zt.s}, 'Pgl, ['Xns, 'Rm, lsl #2]"; - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusImm( - const Instruction *instr) { - const char *form = (instr->ExtractBits(21, 16) != 0) - ? "'prefSVEOp, 'Pgl, ['Xns, #'s2116, mul vl]" - : "'prefSVEOp, 'Pgl, ['Xns]"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEContiguousPrefetch_ScalarPlusScalar( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEContiguousPrefetch_ScalarPlusScalar)"; - - if (instr->GetRm() != kZeroRegCode) { - switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) { - case PRFB_i_p_br_s: - mnemonic = "prfb"; - form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm]"; - break; - case PRFD_i_p_br_s: - mnemonic = "prfd"; - form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #3]"; - break; - case PRFH_i_p_br_s: - mnemonic = "prfh"; - form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #1]"; - break; - case PRFW_i_p_br_s: - mnemonic = "prfw"; - form = "'prefSVEOp, 'Pgl, ['Xns, 'Rm, lsl #2]"; - break; - default: - break; - } - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEContiguousStore_ScalarPlusImm( - const Instruction *instr) { - // The 'size' field isn't in the usual place here. - const char *form = "{'Zt.'tls}, 'Pgl, ['Xns, #'s1916, mul vl]"; - if (instr->ExtractBits(19, 16) == 0) { - form = "{'Zt.'tls}, 'Pgl, ['Xns]"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEContiguousStore_ScalarPlusScalar( - const Instruction *instr) { - // The 'size' field isn't in the usual place here. - FormatWithDecodedMnemonic(instr, "{'Zt.'tls}, 'Pgl, ['Xns, 'Xm'NSveS]"); -} - -void Disassembler::VisitSVECopyFPImm_Predicated(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVECopyFPImm_Predicated)"; - - if (instr->GetSVEVectorFormat() != kFormatVnB) { - switch (instr->Mask(SVECopyFPImm_PredicatedMask)) { - case FCPY_z_p_i: - // The preferred disassembly for fcpy is "fmov". - mnemonic = "fmov"; - form = "'Zd.'t, 'Pm/m, 'IFPSve"; - break; - default: - break; - } - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVECopyGeneralRegisterToVector_Predicated( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVECopyGeneralRegisterToVector_Predicated)"; - - switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) { - case CPY_z_p_r: - // The preferred disassembly for cpy is "mov". - mnemonic = "mov"; - form = "'Zd.'t, 'Pgl/m, 'Wns"; - if (instr->GetSVESize() == kXRegSizeInBytesLog2) { - form = "'Zd.'t, 'Pgl/m, 'Xns"; - } - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVECopyIntImm_Predicated(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVECopyIntImm_Predicated)"; - const char *suffix = NULL; - - switch (instr->Mask(SVECopyIntImm_PredicatedMask)) { - case CPY_z_p_i: { - // The preferred disassembly for cpy is "mov". - mnemonic = "mov"; - form = "'Zd.'t, 'Pm/'?14:mz, #'s1205"; - if (instr->ExtractBit(13) != 0) suffix = ", lsl #8"; - break; - } - default: - break; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVECopySIMDFPScalarRegisterToVector_Predicated( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVECopySIMDFPScalarRegisterToVector_Predicated)"; - - switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) { - case CPY_z_p_v: - // The preferred disassembly for cpy is "mov". - mnemonic = "mov"; - form = "'Zd.'t, 'Pgl/m, 'Vnv"; - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEExtractElementToGeneralRegister( - const Instruction *instr) { - const char *form = "'Wd, 'Pgl, 'Zn.'t"; - if (instr->GetSVESize() == kDRegSizeInBytesLog2) { - form = "'Xd, p'u1210, 'Zn.'t"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEExtractElementToSIMDFPScalarRegister( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 'Zn.'t"); -} - -void Disassembler::VisitSVEFFRInitialise(const Instruction *instr) { - DisassembleNoArgs(instr); -} - -void Disassembler::VisitSVEFFRWriteFromPredicate(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pn.b"); -} - -void Disassembler::VisitSVEFPArithmeticWithImm_Predicated( - const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, #"; - const char *suffix00 = "0.0"; - const char *suffix05 = "0.5"; - const char *suffix10 = "1.0"; - const char *suffix20 = "2.0"; - int i1 = instr->ExtractBit(5); - const char *suffix = i1 ? suffix10 : suffix00; - - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - return; - } - - switch (form_hash_) { - case "fadd_z_p_zs"_h: - case "fsubr_z_p_zs"_h: - case "fsub_z_p_zs"_h: - suffix = i1 ? suffix10 : suffix05; - break; - case "fmul_z_p_zs"_h: - suffix = i1 ? suffix20 : suffix05; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEFPArithmetic_Predicated(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { + uint64_t imm = instr->GetSVEImmLogical(); + if (imm == 0) { VisitUnallocated(instr); } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); + int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2(); + const char *mnemonic = + SVEMoveMaskPreferred(imm, lane_size) ? "mov" : "dupm"; + const char *form = "'Zd.'(17?d:'[sszlog]), 'ITriSvel"; + Format(instr, mnemonic, form); } } -void Disassembler::VisitSVEFPConvertPrecision(const Instruction *instr) { - const char *form = NULL; - - switch (form_hash_) { - case "fcvt_z_p_z_d2h"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.d"; - break; - case "fcvt_z_p_z_d2s"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.d"; - break; - case "fcvt_z_p_z_h2d"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.h"; - break; - case "fcvt_z_p_z_h2s"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.h"; - break; - case "fcvt_z_p_z_s2d"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.s"; - break; - case "fcvt_z_p_z_s2h"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.s"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEFPConvertToInt(const Instruction *instr) { - const char *form = NULL; - - switch (form_hash_) { - case "fcvtzs_z_p_z_d2w"_h: - case "fcvtzu_z_p_z_d2w"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.d"; - break; - case "fcvtzs_z_p_z_d2x"_h: - case "fcvtzu_z_p_z_d2x"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.d"; - break; - case "fcvtzs_z_p_z_fp162h"_h: - case "fcvtzu_z_p_z_fp162h"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.h"; - break; - case "fcvtzs_z_p_z_fp162w"_h: - case "fcvtzu_z_p_z_fp162w"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.h"; - break; - case "fcvtzs_z_p_z_fp162x"_h: - case "fcvtzu_z_p_z_fp162x"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.h"; - break; - case "fcvtzs_z_p_z_s2w"_h: - case "fcvtzu_z_p_z_s2w"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.s"; - break; - case "fcvtzs_z_p_z_s2x"_h: - case "fcvtzu_z_p_z_s2x"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.s"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEFPExponentialAccelerator(const Instruction *instr) { - unsigned size = instr->GetSVESize(); - if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) || - (size == kDRegSizeInBytesLog2)) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEFPRoundToIntegralValue(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t"); - } -} - -void Disassembler::VisitSVEFPTrigMulAddCoefficient(const Instruction *instr) { - unsigned size = instr->GetSVESize(); - if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) || - (size == kDRegSizeInBytesLog2)) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zd.'t, 'Zn.'t, #'u1816"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEFPTrigSelectCoefficient(const Instruction *instr) { - unsigned size = instr->GetSVESize(); - if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) || - (size == kDRegSizeInBytesLog2)) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEFPUnaryOp(const Instruction *instr) { - if (instr->GetSVESize() == kBRegSizeInBytesLog2) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t"); - } -} - -static const char *IncDecFormHelper(const Instruction *instr, - const char *reg_pat_mul_form, - const char *reg_pat_form, - const char *reg_form) { - if (instr->ExtractBits(19, 16) == 0) { - if (instr->ExtractBits(9, 5) == SVE_ALL) { - // Use the register only form if the multiplier is one (encoded as zero) - // and the pattern is SVE_ALL. - return reg_form; - } - // Use the register and pattern form if the multiplier is one. - return reg_pat_form; - } - return reg_pat_mul_form; -} - -void Disassembler::VisitSVEIncDecRegisterByElementCount( - const Instruction *instr) { - const char *form = - IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd"); - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIncDecVectorByElementCount( - const Instruction *instr) { - const char *form = IncDecFormHelper(instr, - "'Zd.'t, 'Ipc, mul #'u1916+1", - "'Zd.'t, 'Ipc", - "'Zd.'t"); - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEInsertGeneralRegister(const Instruction *instr) { - const char *form = "'Zd.'t, 'Wn"; - if (instr->GetSVESize() == kDRegSizeInBytesLog2) { - form = "'Zd.'t, 'Xn"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEInsertSIMDFPScalarRegister( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Vnv"); -} - -void Disassembler::VisitSVEIntAddSubtractImm_Unpredicated( - const Instruction *instr) { - const char *form = (instr->ExtractBit(13) == 0) - ? "'Zd.'t, 'Zd.'t, #'u1205" - : "'Zd.'t, 'Zd.'t, #'u1205, lsl #8"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIntAddSubtractVectors_Predicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEIntCompareScalarCountAndLimit( - const Instruction *instr) { - const char *form = - (instr->ExtractBit(12) == 0) ? "'Pd.'t, 'Wn, 'Wm" : "'Pd.'t, 'Xn, 'Xm"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIntConvertToFP(const Instruction *instr) { - const char *form = NULL; - switch (form_hash_) { - case "scvtf_z_p_z_h2fp16"_h: - case "ucvtf_z_p_z_h2fp16"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.h"; - break; - case "scvtf_z_p_z_w2d"_h: - case "ucvtf_z_p_z_w2d"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.s"; - break; - case "scvtf_z_p_z_w2fp16"_h: - case "ucvtf_z_p_z_w2fp16"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.s"; - break; - case "scvtf_z_p_z_w2s"_h: - case "ucvtf_z_p_z_w2s"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.s"; - break; - case "scvtf_z_p_z_x2d"_h: - case "ucvtf_z_p_z_x2d"_h: - form = "'Zd.d, 'Pgl/m, 'Zn.d"; - break; - case "scvtf_z_p_z_x2fp16"_h: - case "ucvtf_z_p_z_x2fp16"_h: - form = "'Zd.h, 'Pgl/m, 'Zn.d"; - break; - case "scvtf_z_p_z_x2s"_h: - case "ucvtf_z_p_z_x2s"_h: - form = "'Zd.s, 'Pgl/m, 'Zn.d"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIntDivideVectors_Predicated( - const Instruction *instr) { - unsigned size = instr->GetSVESize(); - if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEIntMinMaxDifference_Predicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEIntMinMaxImm_Unpredicated(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zd.'t, #"; - const char *suffix = "'u1205"; - - switch (form_hash_) { - case "smax_z_zi"_h: - case "smin_z_zi"_h: - suffix = "'s1205"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEIntMulImm_Unpredicated(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zd.'t, #'s1205"); -} - -void Disassembler::VisitSVEIntMulVectors_Predicated(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVELoadAndBroadcastElement(const Instruction *instr) { - const char *form = "(SVELoadAndBroadcastElement)"; - const char *suffix_b = ", #'u2116]"; - const char *suffix_h = ", #'u2116*2]"; - const char *suffix_w = ", #'u2116*4]"; - const char *suffix_d = ", #'u2116*8]"; - const char *suffix = NULL; - - switch (form_hash_) { - case "ld1rb_z_p_bi_u8"_h: - form = "{'Zt.b}, 'Pgl/z, ['Xns"; - suffix = suffix_b; - break; - case "ld1rb_z_p_bi_u16"_h: - case "ld1rsb_z_p_bi_s16"_h: - form = "{'Zt.h}, 'Pgl/z, ['Xns"; - suffix = suffix_b; - break; - case "ld1rb_z_p_bi_u32"_h: - case "ld1rsb_z_p_bi_s32"_h: - form = "{'Zt.s}, 'Pgl/z, ['Xns"; - suffix = suffix_b; - break; - case "ld1rb_z_p_bi_u64"_h: - case "ld1rsb_z_p_bi_s64"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns"; - suffix = suffix_b; - break; - case "ld1rh_z_p_bi_u16"_h: - form = "{'Zt.h}, 'Pgl/z, ['Xns"; - suffix = suffix_h; - break; - case "ld1rh_z_p_bi_u32"_h: - case "ld1rsh_z_p_bi_s32"_h: - form = "{'Zt.s}, 'Pgl/z, ['Xns"; - suffix = suffix_h; - break; - case "ld1rh_z_p_bi_u64"_h: - case "ld1rsh_z_p_bi_s64"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns"; - suffix = suffix_h; - break; - case "ld1rw_z_p_bi_u32"_h: - form = "{'Zt.s}, 'Pgl/z, ['Xns"; - suffix = suffix_w; - break; - case "ld1rsw_z_p_bi_s64"_h: - case "ld1rw_z_p_bi_u64"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns"; - suffix = suffix_w; - break; - case "ld1rd_z_p_bi_u64"_h: - form = "{'Zt.d}, 'Pgl/z, ['Xns"; - suffix = suffix_d; - break; - } - - // Hide curly brackets if immediate is zero. - if (instr->ExtractBits(21, 16) == 0) { - suffix = "]"; - } - - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns"; - const char *suffix = ", #'s1916*16]"; - - switch (form_hash_) { - case "ld1rob_z_p_bi_u8"_h: - case "ld1rod_z_p_bi_u64"_h: - case "ld1roh_z_p_bi_u16"_h: - case "ld1row_z_p_bi_u32"_h: - suffix = ", #'s1916*32]"; - break; - } - if (instr->ExtractBits(19, 16) == 0) suffix = "]"; - - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz}, 'Pgl/z, ['Xns, "; - const char *suffix = "'Rm, lsl #'u2423]"; - - switch (form_hash_) { - case "ld1rqb_z_p_br_contiguous"_h: - case "ld1rob_z_p_br_contiguous"_h: - suffix = "'Rm]"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}"; - const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}"; - const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}"; - const char *suffix = ", 'Pgl/z, ['Xns'ISveSvl]"; - - switch (form_hash_) { - case "ld3b_z_p_bi_contiguous"_h: - case "ld3d_z_p_bi_contiguous"_h: - case "ld3h_z_p_bi_contiguous"_h: - case "ld3w_z_p_bi_contiguous"_h: - form = form_3; - break; - case "ld4b_z_p_bi_contiguous"_h: - case "ld4d_z_p_bi_contiguous"_h: - case "ld4h_z_p_bi_contiguous"_h: - case "ld4w_z_p_bi_contiguous"_h: - form = form_4; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVELoadMultipleStructures_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}"; - const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}"; - const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}"; - const char *suffix = ", 'Pgl/z, ['Xns, 'Xm'NSveS]"; - - switch (form_hash_) { - case "ld3b_z_p_br_contiguous"_h: - case "ld3d_z_p_br_contiguous"_h: - case "ld3h_z_p_br_contiguous"_h: - case "ld3w_z_p_br_contiguous"_h: - form = form_3; - break; - case "ld4b_z_p_br_contiguous"_h: - case "ld4d_z_p_br_contiguous"_h: - case "ld4h_z_p_br_contiguous"_h: - case "ld4w_z_p_br_contiguous"_h: - form = form_4; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVELoadPredicateRegister(const Instruction *instr) { - const char *form = "'Pd, ['Xns, #'s2116:1210, mul vl]"; - if (instr->Mask(0x003f1c00) == 0) { - form = "'Pd, ['Xns]"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVELoadVectorRegister(const Instruction *instr) { - const char *form = "'Zt, ['Xns, #'s2116:1210, mul vl]"; - if (instr->Mask(0x003f1c00) == 0) { - form = "'Zd, ['Xns]"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEPartitionBreakCondition(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/'?04:mz, 'Pn.b"); -} - -void Disassembler::VisitSVEPermutePredicateElements(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn.'t, 'Pm.'t"); -} - -void Disassembler::VisitSVEPredicateFirstActive(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b, 'Pn, 'Pd.b"); -} - -void Disassembler::VisitSVEPredicateReadFromFFR_Unpredicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b"); -} - -void Disassembler::VisitSVEPredicateTest(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "p'u1310, 'Pn.b"); -} - -void Disassembler::VisitSVEPredicateZero(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b"); -} - -void Disassembler::VisitSVEPropagateBreakToNextPartition( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/z, 'Pn.b, 'Pd.b"); -} - -void Disassembler::VisitSVEReversePredicateElements(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn.'t"); -} - -void Disassembler::VisitSVEReverseVectorElements(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEReverseWithinElements(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t"; - - unsigned size = instr->GetSVESize(); - switch (instr->Mask(SVEReverseWithinElementsMask)) { - case RBIT_z_p_z: - mnemonic = "rbit"; - break; - case REVB_z_z: - if ((size == kHRegSizeInBytesLog2) || (size == kSRegSizeInBytesLog2) || - (size == kDRegSizeInBytesLog2)) { - mnemonic = "revb"; - } else { - form = "(SVEReverseWithinElements)"; - } - break; - case REVH_z_z: - if ((size == kSRegSizeInBytesLog2) || (size == kDRegSizeInBytesLog2)) { - mnemonic = "revh"; - } else { - form = "(SVEReverseWithinElements)"; - } - break; - case REVW_z_z: - if (size == kDRegSizeInBytesLog2) { - mnemonic = "revw"; - } else { - form = "(SVEReverseWithinElements)"; - } - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVESaturatingIncDecRegisterByElementCount( - const Instruction *instr) { - const char *form = IncDecFormHelper(instr, - "'R20d, 'Ipc, mul #'u1916+1", - "'R20d, 'Ipc", - "'R20d"); - const char *form_sx = IncDecFormHelper(instr, - "'Xd, 'Wd, 'Ipc, mul #'u1916+1", - "'Xd, 'Wd, 'Ipc", - "'Xd, 'Wd"); - - switch (form_hash_) { - case "sqdecb_r_rs_sx"_h: - case "sqdecd_r_rs_sx"_h: - case "sqdech_r_rs_sx"_h: - case "sqdecw_r_rs_sx"_h: - case "sqincb_r_rs_sx"_h: - case "sqincd_r_rs_sx"_h: - case "sqinch_r_rs_sx"_h: - case "sqincw_r_rs_sx"_h: - form = form_sx; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVESaturatingIncDecVectorByElementCount( - const Instruction *instr) { - const char *form = IncDecFormHelper(instr, - "'Zd.'t, 'Ipc, mul #'u1916+1", - "'Zd.'t, 'Ipc", - "'Zd.'t"); - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}"; - const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}"; - const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}"; - const char *suffix = ", 'Pgl, ['Xns'ISveSvl]"; - - switch (form_hash_) { - case "st3b_z_p_bi_contiguous"_h: - case "st3h_z_p_bi_contiguous"_h: - case "st3w_z_p_bi_contiguous"_h: - case "st3d_z_p_bi_contiguous"_h: - form = form_3; - break; - case "st4b_z_p_bi_contiguous"_h: - case "st4h_z_p_bi_contiguous"_h: - case "st4w_z_p_bi_contiguous"_h: - case "st4d_z_p_bi_contiguous"_h: - form = form_4; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEStoreMultipleStructures_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.'tmsz, 'Zt2.'tmsz}"; - const char *form_3 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz}"; - const char *form_4 = "{'Zt.'tmsz, 'Zt2.'tmsz, 'Zt3.'tmsz, 'Zt4.'tmsz}"; - const char *suffix = ", 'Pgl, ['Xns, 'Xm'NSveS]"; - - switch (form_hash_) { - case "st3b_z_p_br_contiguous"_h: - case "st3d_z_p_br_contiguous"_h: - case "st3h_z_p_br_contiguous"_h: - case "st3w_z_p_br_contiguous"_h: - form = form_3; - break; - case "st4b_z_p_br_contiguous"_h: - case "st4d_z_p_br_contiguous"_h: - case "st4h_z_p_br_contiguous"_h: - case "st4w_z_p_br_contiguous"_h: - form = form_4; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEStorePredicateRegister(const Instruction *instr) { - const char *form = "'Pd, ['Xns, #'s2116:1210, mul vl]"; - if (instr->Mask(0x003f1c00) == 0) { - form = "'Pd, ['Xns]"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEStoreVectorRegister(const Instruction *instr) { - const char *form = "'Zt, ['Xns, #'s2116:1210, mul vl]"; - if (instr->Mask(0x003f1c00) == 0) { - form = "'Zd, ['Xns]"; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVETableLookup(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, {'Zn.'t}, 'Zm.'t"); -} - -void Disassembler::VisitSVEUnpackPredicateElements(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.h, 'Pn.b"); -} - -void Disassembler::VisitSVEUnpackVectorElements(const Instruction *instr) { - if (instr->GetSVESize() == 0) { - // The lowest lane size of the destination vector is H-sized lane. - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'th"); - } -} - -void Disassembler::VisitSVEVectorSplice(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl, 'Zd.'t, 'Zn.'t"); -} - -void Disassembler::VisitSVEAddressGeneration(const Instruction *instr) { - const char *mnemonic = "adr"; - const char *form = "'Zd.d, ['Zn.d, 'Zm.d"; - const char *suffix = NULL; - - bool msz_is_zero = (instr->ExtractBits(11, 10) == 0); - - switch (instr->Mask(SVEAddressGenerationMask)) { - case ADR_z_az_d_s32_scaled: - suffix = msz_is_zero ? ", sxtw]" : ", sxtw #'u1110]"; - break; - case ADR_z_az_d_u32_scaled: - suffix = msz_is_zero ? ", uxtw]" : ", uxtw #'u1110]"; - break; - case ADR_z_az_s_same_scaled: - case ADR_z_az_d_same_scaled: - form = "'Zd.'t, ['Zn.'t, 'Zm.'t"; - suffix = msz_is_zero ? "]" : ", lsl #'u1110]"; - break; - default: - mnemonic = "unimplemented"; - form = "(SVEAddressGeneration)"; - break; - } - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVEBitwiseLogicalUnpredicated( - const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "'Zd.d, 'Zn.d, 'Zm.d"; - - switch (instr->Mask(SVEBitwiseLogicalUnpredicatedMask)) { - case AND_z_zz: - mnemonic = "and"; - break; - case BIC_z_zz: - mnemonic = "bic"; - break; - case EOR_z_zz: - mnemonic = "eor"; - break; - case ORR_z_zz: - mnemonic = "orr"; - if (instr->GetRn() == instr->GetRm()) { - mnemonic = "mov"; - form = "'Zd.d, 'Zn.d"; - } - break; - default: - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEBitwiseShiftUnpredicated(const Instruction *instr) { - const char *mnemonic = "unimplemented"; - const char *form = "(SVEBitwiseShiftUnpredicated)"; - unsigned tsize = - (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19); - unsigned lane_size = instr->GetSVESize(); - - const char *suffix = NULL; - const char *form_i = "'Zd.'tszs, 'Zn.'tszs, "; - - switch (form_hash_) { - case "asr_z_zi"_h: - case "lsr_z_zi"_h: - case "sri_z_zzi"_h: - case "srsra_z_zi"_h: - case "ssra_z_zi"_h: - case "ursra_z_zi"_h: - case "usra_z_zi"_h: - if (tsize != 0) { - // The tsz field must not be zero. - mnemonic = mnemonic_.c_str(); - form = form_i; - suffix = "'ITriSves"; - } - break; - case "lsl_z_zi"_h: - case "sli_z_zzi"_h: - if (tsize != 0) { - // The tsz field must not be zero. - mnemonic = mnemonic_.c_str(); - form = form_i; - suffix = "'ITriSver"; - } - break; - case "asr_z_zw"_h: - case "lsl_z_zw"_h: - case "lsr_z_zw"_h: - if (lane_size <= kSRegSizeInBytesLog2) { - mnemonic = mnemonic_.c_str(); - form = "'Zd.'t, 'Zn.'t, 'Zm.d"; - } - break; - default: - break; - } - - Format(instr, mnemonic, form, suffix); -} - -void Disassembler::VisitSVEElementCount(const Instruction *instr) { - const char *form = - IncDecFormHelper(instr, "'Xd, 'Ipc, mul #'u1916+1", "'Xd, 'Ipc", "'Xd"); - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEFPAccumulatingReduction(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 't'u0400, 'Zn.'t"); - } -} - -void Disassembler::VisitSVEFPArithmeticUnpredicated(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t"); - } -} - -void Disassembler::VisitSVEFPCompareVectors(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t"); - } -} - -void Disassembler::VisitSVEFPCompareWithZero(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #0.0"); - } -} - -void Disassembler::VisitSVEFPComplexAddition(const Instruction *instr) { - // Bit 15 is always set, so this gives 90 * 1 or 3. - const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t, #'u1615*90"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, form); - } -} - -void Disassembler::VisitSVEFPComplexMulAdd(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t, #'u1413*90"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, form); - } -} - -void Disassembler::VisitSVEFPComplexMulAddIndex(const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2019]"; - const char *suffix = ", #'u1110*90"; - switch (form_hash_) { - case "fcmla_z_zzzi_s"_h: - form = "'Zd.s, 'Zn.s, z'u1916.s['u2020]"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEFPFastReduction(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'t'u0400, 'Pgl, 'Zn.'t"); - } -} - -void Disassembler::VisitSVEFPMulIndex(const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]"; - switch (form_hash_) { - case "fmul_z_zzi_d"_h: - form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]"; - break; - case "fmul_z_zzi_s"_h: - form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEFPMulAdd(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t, 'Zm.'t"); - } -} - -void Disassembler::VisitSVEFPMulAddIndex(const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]"; - switch (form_hash_) { - case "fmla_z_zzzi_s"_h: - case "fmls_z_zzzi_s"_h: - form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]"; - break; - case "fmla_z_zzzi_d"_h: - case "fmls_z_zzzi_d"_h: - form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEFPUnaryOpUnpredicated(const Instruction *instr) { - if (instr->GetSVEVectorFormat() == kFormatVnB) { - VisitUnallocated(instr); - } else { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t"); - } -} - -void Disassembler::VisitSVEIncDecByPredicateCount(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pn"; - switch (form_hash_) { - // , . - case "decp_r_p_r"_h: - case "incp_r_p_r"_h: - form = "'Xd, 'Pn.'t"; - break; - // , ., - case "sqdecp_r_p_r_sx"_h: - case "sqincp_r_p_r_sx"_h: - form = "'Xd, 'Pn.'t, 'Wd"; - break; - // , . - case "sqdecp_r_p_r_x"_h: - case "sqincp_r_p_r_x"_h: - case "uqdecp_r_p_r_x"_h: - case "uqincp_r_p_r_x"_h: - form = "'Xd, 'Pn.'t"; - break; - // , . - case "uqdecp_r_p_r_uw"_h: - case "uqincp_r_p_r_uw"_h: - form = "'Wd, 'Pn.'t"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIndexGeneration(const Instruction *instr) { - const char *form = "'Zd.'t, #'s0905, #'s2016"; - bool w_inputs = - static_cast(instr->GetSVESize()) <= kWRegSizeInBytesLog2; - - switch (form_hash_) { - case "index_z_ir"_h: - form = w_inputs ? "'Zd.'t, #'s0905, 'Wm" : "'Zd.'t, #'s0905, 'Xm"; - break; - case "index_z_ri"_h: - form = w_inputs ? "'Zd.'t, 'Wn, #'s2016" : "'Zd.'t, 'Xn, #'s2016"; - break; - case "index_z_rr"_h: - form = w_inputs ? "'Zd.'t, 'Wn, 'Wm" : "'Zd.'t, 'Xn, 'Xm"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIntArithmeticUnpredicated(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t"); -} - -void Disassembler::VisitSVEIntCompareSignedImm(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #'s2016"); -} - -void Disassembler::VisitSVEIntCompareUnsignedImm(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pgl/z, 'Zn.'t, #'u2014"); -} - -void Disassembler::VisitSVEIntCompareVectors(const Instruction *instr) { - const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm."; - const char *suffix = "d"; - switch (form_hash_) { - case "cmpeq_p_p_zz"_h: - case "cmpge_p_p_zz"_h: - case "cmpgt_p_p_zz"_h: - case "cmphi_p_p_zz"_h: - case "cmphs_p_p_zz"_h: - case "cmpne_p_p_zz"_h: - suffix = "'t"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEIntMulAddPredicated(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, "; - const char *suffix = "'Zn.'t, 'Zm.'t"; - switch (form_hash_) { - case "mad_z_p_zzz"_h: - case "msb_z_p_zzz"_h: - suffix = "'Zm.'t, 'Zn.'t"; - break; - } - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEIntMulAddUnpredicated(const Instruction *instr) { - if (static_cast(instr->GetSVESize()) >= kSRegSizeInBytesLog2) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'tq, 'Zm.'tq"); - } else { - VisitUnallocated(instr); - } -} - -void Disassembler::VisitSVEMovprfx(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/'?16:mz, 'Zn.'t"); -} - -void Disassembler::VisitSVEIntReduction(const Instruction *instr) { - const char *form = "'Vdv, 'Pgl, 'Zn.'t"; - switch (form_hash_) { - case "saddv_r_p_z"_h: - case "uaddv_r_p_z"_h: - form = "'Dd, 'Pgl, 'Zn.'t"; - break; - } - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEIntUnaryArithmeticPredicated( - const Instruction *instr) { - VectorFormat vform = instr->GetSVEVectorFormat(); - - switch (form_hash_) { - case "sxtw_z_p_z"_h: - case "uxtw_z_p_z"_h: - if (vform == kFormatVnS) { - VisitUnallocated(instr); - return; - } - VIXL_FALLTHROUGH(); - case "sxth_z_p_z"_h: - case "uxth_z_p_z"_h: - if (vform == kFormatVnH) { - VisitUnallocated(instr); - return; - } - VIXL_FALLTHROUGH(); - case "sxtb_z_p_z"_h: - case "uxtb_z_p_z"_h: - case "fabs_z_p_z"_h: - case "fneg_z_p_z"_h: - if (vform == kFormatVnB) { - VisitUnallocated(instr); - return; - } - break; - } - - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Pgl/m, 'Zn.'t"); -} - -void Disassembler::VisitSVEMulIndex(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.b, z'u1816.b['u2019]"; - - switch (form_hash_) { - case "sdot_z_zzzi_d"_h: - case "udot_z_zzzi_d"_h: - form = "'Zd.d, 'Zn.h, z'u1916.h['u2020]"; - break; - } - - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEPermuteVectorExtract(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.b, 'Zd.b, 'Zn.b, #'u2016:1210"); -} - -void Disassembler::VisitSVEPermuteVectorInterleaving(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Zd.'t, 'Zn.'t, 'Zm.'t"); -} - -void Disassembler::VisitSVEPredicateCount(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Xd, p'u1310, 'Pn.'t"); -} - -void Disassembler::VisitSVEPredicateLogical(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b"; - - int pd = instr->GetPd(); - int pn = instr->GetPn(); - int pm = instr->GetPm(); - int pg = instr->ExtractBits(13, 10); - - switch (form_hash_) { - case "ands_p_p_pp_z"_h: - if (pn == pm) { - mnemonic = "movs"; - form = "'Pd.b, p'u1310/z, 'Pn.b"; - } - break; - case "and_p_p_pp_z"_h: - if (pn == pm) { - mnemonic = "mov"; - form = "'Pd.b, p'u1310/z, 'Pn.b"; - } - break; - case "eors_p_p_pp_z"_h: - if (pm == pg) { - mnemonic = "nots"; - form = "'Pd.b, 'Pm/z, 'Pn.b"; - } - break; - case "eor_p_p_pp_z"_h: - if (pm == pg) { - mnemonic = "not"; - form = "'Pd.b, 'Pm/z, 'Pn.b"; - } - break; - case "orrs_p_p_pp_z"_h: - if ((pn == pm) && (pn == pg)) { - mnemonic = "movs"; - form = "'Pd.b, 'Pn.b"; - } - break; - case "orr_p_p_pp_z"_h: - if ((pn == pm) && (pn == pg)) { - mnemonic = "mov"; - form = "'Pd.b, 'Pn.b"; - } - break; - case "sel_p_p_pp"_h: - if (pd == pm) { - mnemonic = "mov"; - form = "'Pd.b, p'u1310/m, 'Pn.b"; - } else { - form = "'Pd.b, p'u1310, 'Pn.b, 'Pm.b"; - } - break; - } - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEPredicateInitialize(const Instruction *instr) { - const char *form = "'Pd.'t, 'Ipc"; - // Omit the pattern if it is the default ('ALL'). - if (instr->ExtractBits(9, 5) == SVE_ALL) form = "'Pd.'t"; - FormatWithDecodedMnemonic(instr, form); -} - -void Disassembler::VisitSVEPredicateNextActive(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.'t, 'Pn, 'Pd.'t"); -} - -void Disassembler::VisitSVEPredicateReadFromFFR_Predicated( - const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b, 'Pn/z"); -} - -void Disassembler::VisitSVEPropagateBreak(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Pd.b, p'u1310/z, 'Pn.b, 'Pm.b"); -} - -void Disassembler::VisitSVEStackFrameAdjustment(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Xds, 'Xms, #'s1005"); -} - -void Disassembler::VisitSVEStackFrameSize(const Instruction *instr) { - FormatWithDecodedMnemonic(instr, "'Xd, #'s1005"); -} - -void Disassembler::VisitSVEVectorSelect(const Instruction *instr) { - const char *mnemonic = mnemonic_.c_str(); - const char *form = "'Zd.'t, p'u1310, 'Zn.'t, 'Zm.'t"; - - if (instr->GetRd() == instr->GetRm()) { - mnemonic = "mov"; - form = "'Zd.'t, p'u1310/m, 'Zn.'t"; - } - - Format(instr, mnemonic, form); -} - -void Disassembler::VisitSVEContiguousLoad_ScalarPlusImm( - const Instruction *instr) { - const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns"; - const char *suffix = - (instr->ExtractBits(19, 16) == 0) ? "]" : ", #'s1916, mul vl]"; - FormatWithDecodedMnemonic(instr, form, suffix); -} - -void Disassembler::VisitSVEContiguousLoad_ScalarPlusScalar( - const Instruction *instr) { - const char *form = "{'Zt.'tlss}, 'Pgl/z, ['Xns, 'Xm"; - const char *suffix = "]"; - - switch (form_hash_) { - case "ld1h_z_p_br_u16"_h: - case "ld1h_z_p_br_u32"_h: - case "ld1h_z_p_br_u64"_h: - case "ld1w_z_p_br_u32"_h: - case "ld1w_z_p_br_u64"_h: - case "ld1d_z_p_br_u64"_h: - suffix = ", lsl #'u2423]"; - break; - case "ld1sh_z_p_br_s32"_h: - case "ld1sh_z_p_br_s64"_h: - suffix = ", lsl #1]"; - break; - case "ld1sw_z_p_br_s64"_h: - suffix = ", lsl #2]"; - break; - } - - FormatWithDecodedMnemonic(instr, form, suffix); -} - void Disassembler::VisitReserved(const Instruction *instr) { - // UDF is the only instruction in this group, and the Decoder is precise. - VIXL_ASSERT(instr->Mask(ReservedMask) == UDF); - Format(instr, "udf", "'IUdf"); + FormatWithDecodedMnemonic(instr, "#0x'x1500"); } void Disassembler::VisitUnimplemented(const Instruction *instr) { Format(instr, "unimplemented", "(Unimplemented)"); } - void Disassembler::VisitUnallocated(const Instruction *instr) { Format(instr, "unallocated", "(Unallocated)"); } void Disassembler::Visit(Metadata *metadata, const Instruction *instr) { VIXL_ASSERT(metadata->count("form") > 0); - const std::string &form = (*metadata)["form"]; + // Check for unallocated encodings. + if (metadata->count("unallocated") > 0) { + VisitUnallocated(instr); + return; + } + + std::string form = (*metadata)["form"]; form_hash_ = Hash(form.c_str()); + + // Find the alias of the decoded instruction, if any. + std::string alias = GetMnemonicAlias(instr); + if (alias.length() > 0) { + form = alias + "_" + form; + form_hash_ = Hash(form.c_str()); + } + + // Get the disassembly string for this form or alias. + FormToStringMap::const_iterator its = form_to_string_.find(form_hash_); + if (its != form_to_string_.end()) { + SetMnemonicFromForm(form); + FormatWithDecodedMnemonic(instr, its->second); + return; + } + + if (alias.length() > 0) { + printf("Unhandled %s\n", form.c_str()); + } + // All aliases should be handled by this point. + VIXL_ASSERT(alias.length() == 0); + + // Call a legacy visitor-based handler. const FormToVisitorFnMap *fv = Disassembler::GetFormToVisitorFnMap(); FormToVisitorFnMap::const_iterator it = fv->find(form_hash_); if (it == fv->end()) { @@ -5687,526 +3462,10 @@ void Disassembler::Visit(Metadata *metadata, const Instruction *instr) { } } -void Disassembler::Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction *instr) { - const char *form = "'Pd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t"; - VectorFormat vform = instr->GetSVEVectorFormat(); - - if ((vform == kFormatVnS) || (vform == kFormatVnD)) { - Format(instr, "unimplemented", "(PdT_PgZ_ZnT_ZmT)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction *instr) { - const char *form = "'Zd.b, {'Zn.b, 'Zn2.b}, #'u2016:1210"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdB_ZnB_ZmB(const Instruction *instr) { - const char *form = "'Zd.b, 'Zn.b, 'Zm.b"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(ZdB_ZnB_ZmB)"); - } -} - -void Disassembler::Disassemble_ZdD_PgM_ZnS(const Instruction *instr) { - const char *form = "'Zd.d, 'Pgl/m, 'Zn.s"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdD_ZnD_ZmD(const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.d, 'Zm.d"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdD_ZnD_ZmD_imm(const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdD_ZnS_ZmS_imm(const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdH_PgM_ZnS(const Instruction *instr) { - const char *form = "'Zd.h, 'Pgl/m, 'Zn.s"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdH_ZnH_ZmH_imm(const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdS_PgM_ZnD(const Instruction *instr) { - const char *form = "'Zd.s, 'Pgl/m, 'Zn.d"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdS_PgM_ZnH(const Instruction *instr) { - const char *form = "'Zd.s, 'Pgl/m, 'Zn.h"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdS_PgM_ZnS(const Instruction *instr) { - const char *form = "'Zd.s, 'Pgl/m, 'Zn.s"; - if (instr->GetSVEVectorFormat() == kFormatVnS) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(ZdS_PgM_ZnS)"); - } -} - -void Disassembler::Disassemble_ZdS_ZnH_ZmH_imm(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdS_ZnS_ZmS(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.s, 'Zm.s"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdS_ZnS_ZmS_imm(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSVEFlogb(const Instruction *instr) { - const char *form = "'Zd.'tf, 'Pgl/m, 'Zn.'tf"; - if (instr->GetSVEVectorFormat(17) == kFormatVnB) { - Format(instr, "unimplemented", "(SVEFlogb)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdT_PgM_ZnT(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'t"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/z, 'Zn.'t, 'Zm.'t"; - VectorFormat vform = instr->GetSVEVectorFormat(); - if ((vform == kFormatVnS) || (vform == kFormatVnD)) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(ZdT_PgZ_ZnT_ZmT)"); - } -} - -void Disassembler::Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl, {'Zn.'t, 'Zn2.'t}"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction *instr) { - const char *form = "'Zd.'t, {'Zn.'t, 'Zn2.'t}, 'Zm.'t"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdT_ZnT_ZmT(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdT_ZnT_ZmTb(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'th"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - Format(instr, "unimplemented", "(ZdT_ZnT_ZmTb)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdT_ZnTb(const Instruction *instr) { - const char *form = "'Zd.'tszs, 'Zn.'tszd"; - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); - int shift_dist = shift_and_lane_size.first; - int lane_size = shift_and_lane_size.second; - // Convert shift_dist from a right to left shift. Valid xtn instructions - // must have a left shift_dist equivalent of zero. - shift_dist = (8 << lane_size) - shift_dist; - if ((lane_size >= static_cast(kBRegSizeInBytesLog2)) && - (lane_size <= static_cast(kSRegSizeInBytesLog2)) && - (shift_dist == 0)) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(ZdT_ZnTb)"); - } -} - -void Disassembler::Disassemble_ZdT_ZnTb_ZmTb(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - // TODO: This is correct for saddlbt, ssublbt, subltb, which don't have - // b-lane sized form, and for pmull[b|t] as feature `SVEPmull128` isn't - // supported, but may need changes for other instructions reaching here. - Format(instr, "unimplemented", "(ZdT_ZnTb_ZmTb)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::DisassembleSVEAddSubHigh(const Instruction *instr) { - const char *form = "'Zd.'th, 'Zn.'t, 'Zm.'t"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - Format(instr, "unimplemented", "(SVEAddSubHigh)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::DisassembleSVEShiftLeftImm(const Instruction *instr) { - const char *form = "'Zd.'tszd, 'Zn.'tszs, 'ITriSver"; - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); - int lane_size = shift_and_lane_size.second; - if ((lane_size >= static_cast(kBRegSizeInBytesLog2)) && - (lane_size <= static_cast(kSRegSizeInBytesLog2))) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(SVEShiftLeftImm)"); - } -} - -void Disassembler::DisassembleSVEShiftRightImm(const Instruction *instr) { - const char *form = "'Zd.'tszs, 'Zn.'tszd, 'ITriSves"; - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); - int lane_size = shift_and_lane_size.second; - if ((lane_size >= static_cast(kBRegSizeInBytesLog2)) && - (lane_size <= static_cast(kSRegSizeInBytesLog2))) { - Format(instr, mnemonic_.c_str(), form); - } else { - Format(instr, "unimplemented", "(SVEShiftRightImm)"); - } -} - -void Disassembler::Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.d, z'u1916.d['u2020]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaD_ZnH_ZmH_imm_const( - const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.h, z'u1916.h['u2020], #'u1110*90"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction *instr) { - const char *form = "'Zd.d, 'Zn.s, z'u1916.s['u2020:1111]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2222:2019]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaH_ZnH_ZmH_imm_const( - const Instruction *instr) { - const char *form = "'Zd.h, 'Zn.h, z'u1816.h['u2019], #'u1110*90"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnB_ZmB(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.b, 'Zm.b"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnB_ZmB_imm_const( - const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.b, z'u1816.b['u2019], #'u1110*90"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnH_ZmH(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.h, 'Zm.h"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.h, z'u1816.h['u2019:1111]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.s, z'u1816.s['u2019]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaS_ZnS_ZmS_imm_const( - const Instruction *instr) { - const char *form = "'Zd.s, 'Zn.s, z'u1916.s['u2020], #'u1110*90"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaT_PgM_ZnTb(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zn.'th"; - - if (instr->GetSVESize() == 0) { - // The lowest lane size of the destination vector is H-sized lane. - Format(instr, "unimplemented", "(Disassemble_ZdaT_PgM_ZnTb)"); - return; - } - - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSVEAddSubCarry(const Instruction *instr) { - const char *form = "'Zd.'?22:ds, 'Zn.'?22:ds, 'Zm.'?22:ds"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaT_ZnT_ZmT(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaT_ZnT_ZmT_const(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'t, 'Zm.'t, #'u1110*90"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'th, 'Zm.'th"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zn.'tq, 'Zm.'tq, #'u1110*90"; - VectorFormat vform = instr->GetSVEVectorFormat(); - - if ((vform == kFormatVnB) || (vform == kFormatVnH)) { - Format(instr, "unimplemented", "(ZdaT_ZnTb_ZmTb_const)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdnB_ZdnB(const Instruction *instr) { - const char *form = "'Zd.b, 'Zd.b"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdnB_ZdnB_ZmB(const Instruction *instr) { - const char *form = "'Zd.b, 'Zd.b, 'Zn.b"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSVEBitwiseTernary(const Instruction *instr) { - const char *form = "'Zd.d, 'Zd.d, 'Zm.d, 'Zn.d"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_ZdnS_ZdnS_ZmS(const Instruction *instr) { - const char *form = "'Zd.s, 'Zd.s, 'Zn.s"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSVEFPPair(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"; - if (instr->GetSVEVectorFormat() == kFormatVnB) { - Format(instr, "unimplemented", "(SVEFPPair)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction *instr) { - const char *form = "'Zd.'t, 'Pgl/m, 'Zd.'t, 'Zn.'t"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSVEComplexIntAddition(const Instruction *instr) { - const char *form = "'Zd.'t, 'Zd.'t, 'Zn.'t, #"; - const char *suffix = (instr->ExtractBit(10) == 0) ? "90" : "270"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction *instr) { - const char *form = "'Zd.'tszs, 'Zd.'tszs, 'Zn.'tszs, 'ITriSves"; - unsigned tsize = - (instr->ExtractBits(23, 22) << 2) | instr->ExtractBits(20, 19); - - if (tsize == 0) { - Format(instr, "unimplemented", "(ZdnT_ZdnT_ZmT_const)"); - } else { - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction *instr) { - const char *form = "{'Zt.d}, 'Pgl/z, ['Zn.d"; - const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_ZtD_Pg_ZnD_Xm(const Instruction *instr) { - const char *form = "{'Zt.d}, 'Pgl, ['Zn.d"; - const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction *instr) { - const char *form = "{'Zt.s}, 'Pgl/z, ['Zn.s"; - const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_ZtS_Pg_ZnS_Xm(const Instruction *instr) { - const char *form = "{'Zt.s}, 'Pgl, ['Zn.s"; - const char *suffix = instr->GetRm() == 31 ? "]" : ", 'Xm]"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_XdSP_XnSP_Xm(const Instruction *instr) { - const char *form = "'Xds, 'Xns"; - const char *suffix = instr->GetRm() == 31 ? "" : ", 'Xm"; - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction *instr) { - VIXL_STATIC_ASSERT(kMTETagGranuleInBytes == 16); - const char *form = "'Xds, 'Xns, #'u2116*16, #'u1310"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_Xd_XnSP_Xm(const Instruction *instr) { - const char *form = "'Rd, 'Xns, 'Rm"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::Disassemble_Xd_XnSP_XmSP(const Instruction *instr) { - if ((form_hash_ == Hash("subps_64s_dp_2src")) && (instr->GetRd() == 31)) { - Format(instr, "cmpp", "'Xns, 'Xms"); - } else { - const char *form = "'Xd, 'Xns, 'Xms"; - Format(instr, mnemonic_.c_str(), form); - } -} - -void Disassembler::DisassembleMTEStoreTagPair(const Instruction *instr) { - const char *form = "'Xt, 'Xt2, ['Xns"; - const char *suffix = NULL; - switch (form_hash_) { - case Hash("stgp_64_ldstpair_off"): - suffix = ", #'s2115*16]"; - break; - case Hash("stgp_64_ldstpair_post"): - suffix = "], #'s2115*16"; - break; - case Hash("stgp_64_ldstpair_pre"): - suffix = ", #'s2115*16]!"; - break; - default: - mnemonic_ = "unimplemented"; - break; - } - - if (instr->GetImmLSPair() == 0) { - suffix = "]"; - } - - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::DisassembleMTEStoreTag(const Instruction *instr) { - const char *form = "'Xds, ['Xns"; - const char *suffix = NULL; - switch (form_hash_) { - case Hash("st2g_64soffset_ldsttags"): - case Hash("stg_64soffset_ldsttags"): - case Hash("stz2g_64soffset_ldsttags"): - case Hash("stzg_64soffset_ldsttags"): - suffix = ", #'s2012*16]"; - break; - case Hash("st2g_64spost_ldsttags"): - case Hash("stg_64spost_ldsttags"): - case Hash("stz2g_64spost_ldsttags"): - case Hash("stzg_64spost_ldsttags"): - suffix = "], #'s2012*16"; - break; - case Hash("st2g_64spre_ldsttags"): - case Hash("stg_64spre_ldsttags"): - case Hash("stz2g_64spre_ldsttags"): - case Hash("stzg_64spre_ldsttags"): - suffix = ", #'s2012*16]!"; - break; - default: - mnemonic_ = "unimplemented"; - break; - } - - if (instr->GetImmLS() == 0) { - suffix = "]"; - } - - Format(instr, mnemonic_.c_str(), form, suffix); -} - -void Disassembler::DisassembleMTELoadTag(const Instruction *instr) { - const char *form = - (instr->GetImmLS() == 0) ? "'Xt, ['Xns]" : "'Xt, ['Xns, #'s2012*16]"; - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleCpy(const Instruction *instr) { - const char *form = "['Xd]!, ['Xs]!, 'Xn!"; - - int d = instr->GetRd(); - int n = instr->GetRn(); - int s = instr->GetRs(); - - // Aliased registers and sp/zr are disallowed. - if ((d == n) || (d == s) || (n == s) || (d == 31) || (n == 31) || (s == 31)) { - form = NULL; - } - - // Bits 31 and 30 must be zero. - if (instr->ExtractBits(31, 30)) { - form = NULL; - } - - Format(instr, mnemonic_.c_str(), form); -} - -void Disassembler::DisassembleSet(const Instruction *instr) { - const char *form = "['Xd]!, 'Xn!, 'Xs"; - - int d = instr->GetRd(); - int n = instr->GetRn(); - int s = instr->GetRs(); - - // Aliased registers are disallowed. Only Xs may be xzr. - if ((d == n) || (d == s) || (n == s) || (d == 31) || (n == 31)) { - form = NULL; - } - - // Bits 31 and 30 must be zero. - if (instr->ExtractBits(31, 30)) { - form = NULL; - } - - Format(instr, mnemonic_.c_str(), form); -} - void Disassembler::ProcessOutput(const Instruction * /*instr*/) { // The base disasm does nothing more than disassembling into a buffer. } - void Disassembler::AppendRegisterNameToOutput(const Instruction *instr, const CPURegister ®) { USE(instr); @@ -6248,7 +3507,6 @@ void Disassembler::AppendRegisterNameToOutput(const Instruction *instr, } } - void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr, int64_t offset) { USE(instr); @@ -6261,26 +3519,22 @@ void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction *instr, } } - void Disassembler::AppendAddressToOutput(const Instruction *instr, const void *addr) { USE(instr); AppendToOutput("(addr 0x%" PRIxPTR ")", reinterpret_cast(addr)); } - void Disassembler::AppendCodeAddressToOutput(const Instruction *instr, const void *addr) { AppendAddressToOutput(instr, addr); } - void Disassembler::AppendDataAddressToOutput(const Instruction *instr, const void *addr) { AppendAddressToOutput(instr, addr); } - void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr, const void *addr) { USE(instr); @@ -6292,19 +3546,16 @@ void Disassembler::AppendCodeRelativeAddressToOutput(const Instruction *instr, } } - void Disassembler::AppendCodeRelativeCodeAddressToOutput( const Instruction *instr, const void *addr) { AppendCodeRelativeAddressToOutput(instr, addr); } - void Disassembler::AppendCodeRelativeDataAddressToOutput( const Instruction *instr, const void *addr) { AppendCodeRelativeAddressToOutput(instr, addr); } - void Disassembler::MapCodeAddress(int64_t base_address, const Instruction *instr_address) { set_code_address_offset(base_address - @@ -6314,7 +3565,6 @@ int64_t Disassembler::CodeRelativeAddress(const void *addr) { return reinterpret_cast(addr) + code_address_offset(); } - void Disassembler::Format(const Instruction *instr, const char *mnemonic, const char *format0, @@ -6327,10 +3577,16 @@ void Disassembler::Format(const Instruction *instr, if (format0[0] != 0) { // Not a zero-length string. VIXL_ASSERT(buffer_pos_ < buffer_size_); buffer_[buffer_pos_++] = ' '; - Substitute(instr, format0); + int chars_written = Substitute(instr, format0); // TODO: consider using a zero-length string here, too. if (format1 != NULL) { - Substitute(instr, format1); + chars_written += Substitute(instr, format1); + } + + if (chars_written == 0) { + // Erase the space written earlier, as there are no arguments to the + // instruction. + buffer_pos_--; } } VIXL_ASSERT(buffer_pos_ < buffer_size_); @@ -6345,24 +3601,26 @@ void Disassembler::FormatWithDecodedMnemonic(const Instruction *instr, Format(instr, mnemonic_.c_str(), format0, format1); } -void Disassembler::Substitute(const Instruction *instr, const char *string) { +int Disassembler::Substitute(const Instruction *instr, const char *string) { + uint32_t buffer_pos_init = buffer_pos_; char chr = *string++; while (chr != '\0') { if (chr == '\'') { - string += SubstituteField(instr, string); + int offset = SubstituteField(instr, string); + if (offset == 0) break; + string += offset; } else { VIXL_ASSERT(buffer_pos_ < buffer_size_); buffer_[buffer_pos_++] = chr; } chr = *string++; } + return static_cast(buffer_pos_ - buffer_pos_init); } - int Disassembler::SubstituteField(const Instruction *instr, const char *format) { switch (format[0]) { - // NB. The remaining substitution prefix upper-case characters are: JU. case 'R': // Register. X or W, selected by sf (or alternative) bit. case 'F': // FP register. S or D, selected by type field. case 'V': // Vector register, V, vector format. @@ -6381,33 +3639,29 @@ int Disassembler::SubstituteField(const Instruction *instr, return SubstituteImmediateField(instr, format); case 'L': return SubstituteLiteralField(instr, format); - case 'N': - return SubstituteShiftField(instr, format); - case 'C': - return SubstituteConditionField(instr, format); - case 'E': - return SubstituteExtendField(instr, format); case 'A': return SubstitutePCRelAddressField(instr, format); case 'T': return SubstituteBranchTargetField(instr, format); - case 'O': - return SubstituteLSRegOffsetField(instr, format); - case 'M': - return SubstituteBarrierField(instr, format); - case 'K': - return SubstituteCrField(instr, format); - case 'G': - return SubstituteSysOpField(instr, format); - case 'p': - return SubstitutePrefetchField(instr, format); case 'u': case 's': + case 'x': + case 'n': return SubstituteIntField(instr, format); - case 't': - return SubstituteSVESize(instr, format); + case 'f': + return SubstituteFPField(instr, format); case '?': return SubstituteTernary(instr, format); + case '(': + return SubstituteConditionalBlock(instr, format); + case '[': + return SubstituteGenericArray(instr, format); + case '{': + return SubstituteGenericHash(instr, format); + case '<': + return SubstituteExpression(instr, format); + case '$': + return SubstituteEnd(instr, format); default: { VIXL_UNREACHABLE(); return 1; @@ -6485,6 +3739,13 @@ std::pair Disassembler::GetRegNumForField( return std::make_pair(reg_num, field_len); } +int BitPositionFromString(const char *c) { + VIXL_ASSERT(strspn(c, "0123456789") >= 2); + int pos = ((c[0] - '0') * 10) + (c[1] - '0'); + VIXL_ASSERT(pos <= 31); + return pos; +} + int Disassembler::SubstituteRegisterField(const Instruction *instr, const char *format) { unsigned field_len = 1; // Initially, count only the first character. @@ -6503,8 +3764,7 @@ int Disassembler::SubstituteRegisterField(const Instruction *instr, // Core W or X registers where the type is determined by a specified bit // position, eg. 'R20d, 'R05n. This is like the 'Rd syntax, where bit 31 // is implicitly used to select between W and X. - int bitpos = ((reg_field[0] - '0') * 10) + (reg_field[1] - '0'); - VIXL_ASSERT(bitpos <= 31); + int bitpos = BitPositionFromString(reg_field); is_x = (instr->ExtractBit(bitpos) == 1); reg_field = &format[3]; field_len += 2; @@ -6647,112 +3907,6 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, VIXL_ASSERT(format[0] == 'I'); switch (format[1]) { - case 'M': { // IMoveImm, IMoveNeg or IMoveLSL. - if (format[5] == 'L') { - AppendToOutput("#0x%" PRIx32, instr->GetImmMoveWide()); - if (instr->GetShiftMoveWide() > 0) { - AppendToOutput(", lsl #%" PRId32, 16 * instr->GetShiftMoveWide()); - } - } else { - VIXL_ASSERT((format[5] == 'I') || (format[5] == 'N')); - uint64_t imm = static_cast(instr->GetImmMoveWide()) - << (16 * instr->GetShiftMoveWide()); - if (format[5] == 'N') imm = ~imm; - if (!instr->GetSixtyFourBits()) imm &= UINT64_C(0xffffffff); - AppendToOutput("#0x%" PRIx64, imm); - } - return 8; - } - case 'L': { - switch (format[2]) { - case 'L': { // ILLiteral - Immediate Load Literal. - AppendToOutput("pc%+" PRId32, - instr->GetImmLLiteral() * - static_cast(kLiteralEntrySize)); - return 9; - } - case 'S': { // ILS - Immediate Load/Store. - // ILSi - As above, but an index field which must not be - // omitted even if it is zero. - bool is_index = format[3] == 'i'; - if (is_index || (instr->GetImmLS() != 0)) { - AppendToOutput(", #%" PRId32, instr->GetImmLS()); - } - return is_index ? 4 : 3; - } - case 'P': { // ILPx - Immediate Load/Store Pair, x = access size. - // ILPxi - As above, but an index field which must not be - // omitted even if it is zero. - VIXL_ASSERT((format[3] >= '0') && (format[3] <= '9')); - bool is_index = format[4] == 'i'; - if (is_index || (instr->GetImmLSPair() != 0)) { - // format[3] is the scale value. Convert to a number. - int scale = 1 << (format[3] - '0'); - AppendToOutput(", #%" PRId32, instr->GetImmLSPair() * scale); - } - return is_index ? 5 : 4; - } - case 'U': { // ILU - Immediate Load/Store Unsigned. - if (instr->GetImmLSUnsigned() != 0) { - int shift = instr->GetSizeLS(); - AppendToOutput(", #%" PRId32, instr->GetImmLSUnsigned() << shift); - } - return 3; - } - case 'A': { // ILA - Immediate Load with pointer authentication. - if (instr->GetImmLSPAC() != 0) { - AppendToOutput(", #%" PRId32, instr->GetImmLSPAC()); - } - return 3; - } - default: { - VIXL_UNIMPLEMENTED(); - return 0; - } - } - } - case 'C': { // ICondB - Immediate Conditional Branch. - int64_t offset = instr->GetImmCondBranch() << 2; - AppendPCRelativeOffsetToOutput(instr, offset); - return 6; - } - case 'A': { // IAddSub. - int64_t imm = instr->GetImmAddSub() << (12 * instr->GetImmAddSubShift()); - AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm); - return 7; - } - case 'F': { // IFP, IFPNeon, IFPSve or IFPFBits. - int imm8 = 0; - size_t len = strlen("IFP"); - switch (format[3]) { - case 'F': - VIXL_ASSERT(strncmp(format, "IFPFBits", strlen("IFPFBits")) == 0); - AppendToOutput("#%" PRId32, 64 - instr->GetFPScale()); - return static_cast(strlen("IFPFBits")); - case 'N': - VIXL_ASSERT(strncmp(format, "IFPNeon", strlen("IFPNeon")) == 0); - imm8 = instr->GetImmNEONabcdefgh(); - len += strlen("Neon"); - break; - case 'S': - VIXL_ASSERT(strncmp(format, "IFPSve", strlen("IFPSve")) == 0); - imm8 = instr->ExtractBits(12, 5); - len += strlen("Sve"); - break; - default: - VIXL_ASSERT(strncmp(format, "IFP", strlen("IFP")) == 0); - imm8 = instr->GetImmFP(); - break; - } - AppendToOutput("#0x%" PRIx32 " (%.4f)", - imm8, - Instruction::Imm8ToFP32(imm8)); - return static_cast(len); - } - case 'H': { // IH - ImmHint - AppendToOutput("#%" PRId32, instr->GetImmHint()); - return 2; - } case 'T': { // ITri - Immediate Triangular Encoded. if (format[4] == 'S') { VIXL_ASSERT((format[5] == 'v') && (format[6] == 'e')); @@ -6761,40 +3915,6 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, // SVE logical immediate encoding. AppendToOutput("#0x%" PRIx64, instr->GetSVEImmLogical()); return 8; - case 'p': { - // SVE predicated shift immediate encoding, lsl. - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2( - /* is_predicated = */ true); - int lane_bits = 8 << shift_and_lane_size.second; - AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first); - return 8; - } - case 'q': { - // SVE predicated shift immediate encoding, asr and lsr. - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2( - /* is_predicated = */ true); - AppendToOutput("#%" PRId32, shift_and_lane_size.first); - return 8; - } - case 'r': { - // SVE unpredicated shift immediate encoding, left shifts. - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2( - /* is_predicated = */ false); - int lane_bits = 8 << shift_and_lane_size.second; - AppendToOutput("#%" PRId32, lane_bits - shift_and_lane_size.first); - return 8; - } - case 's': { - // SVE unpredicated shift immediate encoding, right shifts. - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2( - /* is_predicated = */ false); - AppendToOutput("#%" PRId32, shift_and_lane_size.first); - return 8; - } default: VIXL_UNREACHABLE(); return 0; @@ -6804,182 +3924,6 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, return 4; } } - case 'N': { // INzcv. - int nzcv = (instr->GetNzcv() << Flags_offset); - AppendToOutput("#%c%c%c%c", - ((nzcv & NFlag) == 0) ? 'n' : 'N', - ((nzcv & ZFlag) == 0) ? 'z' : 'Z', - ((nzcv & CFlag) == 0) ? 'c' : 'C', - ((nzcv & VFlag) == 0) ? 'v' : 'V'); - return 5; - } - case 'P': { // IP - Conditional compare. - AppendToOutput("#%" PRId32, instr->GetImmCondCmp()); - return 2; - } - case 'B': { // Bitfields. - return SubstituteBitfieldImmediateField(instr, format); - } - case 'E': { // IExtract. - AppendToOutput("#%" PRId32, instr->GetImmS()); - return 8; - } - case 't': { // It - Test and branch bit. - AppendToOutput("#%" PRId32, - (instr->GetImmTestBranchBit5() << 5) | - instr->GetImmTestBranchBit40()); - return 2; - } - case 'S': { // ISveSvl - SVE 'mul vl' immediate for structured ld/st. - VIXL_ASSERT(strncmp(format, "ISveSvl", 7) == 0); - int imm = instr->ExtractSignedBits(19, 16); - if (imm != 0) { - int reg_count = instr->ExtractBits(22, 21) + 1; - AppendToOutput(", #%d, mul vl", imm * reg_count); - } - return 7; - } - case 's': { // Is - Shift (immediate). - switch (format[2]) { - case 'R': { // IsR - right shifts. - int shift = 16 << HighestSetBitPosition(instr->GetImmNEONImmh()); - shift -= instr->GetImmNEONImmhImmb(); - AppendToOutput("#%d", shift); - return 3; - } - case 'L': { // IsL - left shifts. - int shift = instr->GetImmNEONImmhImmb(); - shift -= 8 << HighestSetBitPosition(instr->GetImmNEONImmh()); - AppendToOutput("#%d", shift); - return 3; - } - default: { - VIXL_UNIMPLEMENTED(); - return 0; - } - } - } - case 'D': { // IDebug - HLT and BRK instructions. - AppendToOutput("#0x%" PRIx32, instr->GetImmException()); - return 6; - } - case 'U': { // IUdf - UDF immediate. - AppendToOutput("#0x%" PRIx32, instr->GetImmUdf()); - return 4; - } - case 'V': { // Immediate Vector. - switch (format[2]) { - case 'E': { // IVExtract. - AppendToOutput("#%" PRId32, instr->GetImmNEONExt()); - return 9; - } - case 'B': { // IVByElemIndex. - int ret = static_cast(strlen("IVByElemIndex")); - uint32_t vm_index = instr->GetNEONH() << 2; - vm_index |= instr->GetNEONL() << 1; - vm_index |= instr->GetNEONM(); - - static const char *format_rot = "IVByElemIndexRot"; - static const char *format_fhm = "IVByElemIndexFHM"; - if (strncmp(format, format_rot, strlen(format_rot)) == 0) { - // FCMLA uses 'H' bit index when SIZE is 2, else H:L - VIXL_ASSERT((instr->GetNEONSize() == 1) || - (instr->GetNEONSize() == 2)); - vm_index >>= instr->GetNEONSize(); - ret = static_cast(strlen(format_rot)); - } else if (strncmp(format, format_fhm, strlen(format_fhm)) == 0) { - // Nothing to do - FMLAL and FMLSL use H:L:M. - ret = static_cast(strlen(format_fhm)); - } else { - if (instr->GetNEONSize() == 2) { - // S-sized elements use H:L. - vm_index >>= 1; - } else if (instr->GetNEONSize() == 3) { - // D-sized elements use H. - vm_index >>= 2; - } - } - AppendToOutput("%d", vm_index); - return ret; - } - case 'I': { // INS element. - if (strncmp(format, "IVInsIndex", strlen("IVInsIndex")) == 0) { - unsigned rd_index, rn_index; - unsigned imm5 = instr->GetImmNEON5(); - unsigned imm4 = instr->GetImmNEON4(); - int tz = CountTrailingZeros(imm5, 32); - if (tz <= 3) { // Defined for tz = 0 to 3 only. - rd_index = imm5 >> (tz + 1); - rn_index = imm4 >> tz; - if (strncmp(format, "IVInsIndex1", strlen("IVInsIndex1")) == 0) { - AppendToOutput("%d", rd_index); - return static_cast(strlen("IVInsIndex1")); - } else if (strncmp(format, - "IVInsIndex2", - strlen("IVInsIndex2")) == 0) { - AppendToOutput("%d", rn_index); - return static_cast(strlen("IVInsIndex2")); - } - } - return 0; - } else if (strncmp(format, - "IVInsSVEIndex", - strlen("IVInsSVEIndex")) == 0) { - std::pair index_and_lane_size = - instr->GetSVEPermuteIndexAndLaneSizeLog2(); - AppendToOutput("%d", index_and_lane_size.first); - return static_cast(strlen("IVInsSVEIndex")); - } - VIXL_FALLTHROUGH(); - } - case 'L': { // IVLSLane[0123] - suffix indicates access size shift. - AppendToOutput("%d", instr->GetNEONLSIndex(format[8] - '0')); - return 9; - } - case 'M': { // Modified Immediate cases. - if (strncmp(format, "IVMIImm8", strlen("IVMIImm8")) == 0) { - uint64_t imm8 = instr->GetImmNEONabcdefgh(); - AppendToOutput("#0x%" PRIx64, imm8); - return static_cast(strlen("IVMIImm8")); - } else if (strncmp(format, "IVMIImm", strlen("IVMIImm")) == 0) { - uint64_t imm8 = instr->GetImmNEONabcdefgh(); - uint64_t imm = 0; - for (int i = 0; i < 8; ++i) { - if (imm8 & (UINT64_C(1) << i)) { - imm |= (UINT64_C(0xff) << (8 * i)); - } - } - AppendToOutput("#0x%" PRIx64, imm); - return static_cast(strlen("IVMIImm")); - } else if (strncmp(format, - "IVMIShiftAmt1", - strlen("IVMIShiftAmt1")) == 0) { - int cmode = instr->GetNEONCmode(); - int shift_amount = 8 * ((cmode >> 1) & 3); - AppendToOutput("#%d", shift_amount); - return static_cast(strlen("IVMIShiftAmt1")); - } else if (strncmp(format, - "IVMIShiftAmt2", - strlen("IVMIShiftAmt2")) == 0) { - int cmode = instr->GetNEONCmode(); - int shift_amount = 8 << (cmode & 1); - AppendToOutput("#%d", shift_amount); - return static_cast(strlen("IVMIShiftAmt2")); - } else { - VIXL_UNIMPLEMENTED(); - return 0; - } - } - default: { - VIXL_UNIMPLEMENTED(); - return 0; - } - } - } - case 'X': { // IX - CLREX instruction. - AppendToOutput("#0x%" PRIx32, instr->GetCRm()); - return 2; - } case 'Y': { // IY - system register immediate. switch (instr->GetImmSystemRegister()) { case NZCV: @@ -6994,6 +3938,9 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, case RNDRRS: AppendToOutput("rndrrs"); break; + case DCZID_EL0: + AppendToOutput("dczid_el0"); + break; default: AppendToOutput("S%d_%d_c%d_c%d_%d", instr->GetSysOp0(), @@ -7005,60 +3952,6 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, } return 2; } - case 'R': { // IR - Rotate right into flags. - switch (format[2]) { - case 'r': { // IRr - Rotate amount. - AppendToOutput("#%d", instr->GetImmRMIFRotation()); - return 3; - } - default: { - VIXL_UNIMPLEMENTED(); - return 0; - } - } - } - case 'p': { // Ipc - SVE predicate constraint specifier. - VIXL_ASSERT(format[2] == 'c'); - unsigned pattern = instr->GetImmSVEPredicateConstraint(); - switch (pattern) { - // VL1-VL8 are encoded directly. - case SVE_VL1: - case SVE_VL2: - case SVE_VL3: - case SVE_VL4: - case SVE_VL5: - case SVE_VL6: - case SVE_VL7: - case SVE_VL8: - AppendToOutput("vl%u", pattern); - break; - // VL16-VL256 are encoded as log2(N) + c. - case SVE_VL16: - case SVE_VL32: - case SVE_VL64: - case SVE_VL128: - case SVE_VL256: - AppendToOutput("vl%u", 16 << (pattern - SVE_VL16)); - break; - // Special cases. - case SVE_POW2: - AppendToOutput("pow2"); - break; - case SVE_MUL4: - AppendToOutput("mul4"); - break; - case SVE_MUL3: - AppendToOutput("mul3"); - break; - case SVE_ALL: - AppendToOutput("all"); - break; - default: - AppendToOutput("#0x%x", pattern); - break; - } - return 3; - } default: { VIXL_UNIMPLEMENTED(); return 0; @@ -7066,43 +3959,6 @@ int Disassembler::SubstituteImmediateField(const Instruction *instr, } } - -int Disassembler::SubstituteBitfieldImmediateField(const Instruction *instr, - const char *format) { - VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B')); - unsigned r = instr->GetImmR(); - unsigned s = instr->GetImmS(); - - switch (format[2]) { - case 'r': { // IBr. - AppendToOutput("#%d", r); - return 3; - } - case 's': { // IBs+1 or IBs-r+1. - if (format[3] == '+') { - AppendToOutput("#%d", s + 1); - return 5; - } else { - VIXL_ASSERT(format[3] == '-'); - AppendToOutput("#%d", s - r + 1); - return 7; - } - } - case 'Z': { // IBZ-r. - VIXL_ASSERT((format[3] == '-') && (format[4] == 'r')); - unsigned reg_size = - (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize; - AppendToOutput("#%d", reg_size - r); - return 5; - } - default: { - VIXL_UNREACHABLE(); - return 0; - } - } -} - - int Disassembler::SubstituteLiteralField(const Instruction *instr, const char *format) { VIXL_ASSERT(strncmp(format, "LValue", 6) == 0); @@ -7141,77 +3997,6 @@ int Disassembler::SubstituteLiteralField(const Instruction *instr, return 6; } - -int Disassembler::SubstituteShiftField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'N'); - VIXL_ASSERT(instr->GetShiftDP() <= 0x3); - - switch (format[1]) { - case 'D': { // NDP. - VIXL_ASSERT(instr->GetShiftDP() != ROR); - VIXL_FALLTHROUGH(); - } - case 'L': { // NLo. - if (instr->GetImmDPShift() != 0) { - const char *shift_type[] = {"lsl", "lsr", "asr", "ror"}; - AppendToOutput(", %s #%" PRId32, - shift_type[instr->GetShiftDP()], - instr->GetImmDPShift()); - } - return 3; - } - case 'S': { // NSveS (SVE structured load/store indexing shift). - VIXL_ASSERT(strncmp(format, "NSveS", 5) == 0); - int msz = instr->ExtractBits(24, 23); - if (msz > 0) { - AppendToOutput(", lsl #%d", msz); - } - return 5; - } - default: - VIXL_UNIMPLEMENTED(); - return 0; - } -} - - -int Disassembler::SubstituteConditionField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'C'); - const char *condition_code[] = {"eq", - "ne", - "hs", - "lo", - "mi", - "pl", - "vs", - "vc", - "hi", - "ls", - "ge", - "lt", - "gt", - "le", - "al", - "nv"}; - int cond; - switch (format[1]) { - case 'B': - cond = instr->GetConditionBranch(); - break; - case 'I': { - cond = InvertCondition(static_cast(instr->GetCondition())); - break; - } - default: - cond = instr->GetCondition(); - } - AppendToOutput("%s", condition_code[cond]); - return 4; -} - - int Disassembler::SubstitutePCRelAddressField(const Instruction *instr, const char *format) { VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) || // Used by `adr`. @@ -7237,7 +4022,6 @@ int Disassembler::SubstitutePCRelAddressField(const Instruction *instr, return 13; } - int Disassembler::SubstituteBranchTargetField(const Instruction *instr, const char *format) { VIXL_ASSERT(strncmp(format, "TImm", 4) == 0); @@ -7274,165 +4058,53 @@ int Disassembler::SubstituteBranchTargetField(const Instruction *instr, return 8; } +std::pair ExtractIntTerm(const Instruction *instr, + const char *c) { + int32_t bits = 0; + int off = 0; + if (std::isdigit(*c)) { + // Parse decimal and hexadecimal constants. + int base = ((c[0] == '0') && (c[1] == 'x')) ? 16 : 10; -int Disassembler::SubstituteExtendField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(strncmp(format, "Ext", 3) == 0); - VIXL_ASSERT(instr->GetExtendMode() <= 7); - USE(format); - - const char *extend_mode[] = - {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"}; - - // If rd or rn is SP, uxtw on 32-bit registers and uxtx on 64-bit - // registers becomes lsl. - if (((instr->GetRd() == kZeroRegCode) || (instr->GetRn() == kZeroRegCode)) && - (((instr->GetExtendMode() == UXTW) && (instr->GetSixtyFourBits() == 0)) || - (instr->GetExtendMode() == UXTX))) { - if (instr->GetImmExtendShift() > 0) { - AppendToOutput(", lsl #%" PRId32, instr->GetImmExtendShift()); - } + char *new_c; + uint64_t value = strtoul(c, &new_c, base); + off = static_cast(new_c - c); + VIXL_ASSERT(IsInt32(value)); + bits = static_cast(value); } else { - AppendToOutput(", %s", extend_mode[instr->GetExtendMode()]); - if (instr->GetImmExtendShift() > 0) { - AppendToOutput(" #%" PRId32, instr->GetImmExtendShift()); + VIXL_ASSERT(strchr("suxf", *c) != nullptr); + int width = 0; + do { + if (strspn(&c[off + 1], "0123456789") == 2) { + int pos = BitPositionFromString(&c[off + 1]); + bits = (bits << 1) | instr->ExtractBit(pos); + width++; + off += 3; // Skip [usx_] and the two character bit position. + } else { + VIXL_ASSERT(strspn(&c[off + 1], "0123456789") == 4); + int msb = BitPositionFromString(&c[off + 1]); + int lsb = BitPositionFromString(&c[off + 3]); + int chunk_width = msb - lsb + 1; + VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32)); + width += chunk_width; + VIXL_ASSERT(width <= 31); + bits = (bits << chunk_width) | instr->ExtractBits(msb, lsb); + off += 5; // Skip [usx_] and the four character bit position. + } + } while (c[off] == '_'); + VIXL_ASSERT(IsUintN(width, bits)); + + if (c[0] == 's') { + bits = ExtractSignedBitfield32(width - 1, 0, bits); } } - return 3; -} - -int Disassembler::SubstituteLSRegOffsetField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0); - const char *extend_mode[] = {"undefined", - "undefined", - "uxtw", - "lsl", - "undefined", - "undefined", - "sxtw", - "sxtx"}; - USE(format); - - unsigned shift = instr->GetImmShiftLS(); - Extend ext = static_cast(instr->GetExtendMode()); - char reg_type = ((ext == UXTW) || (ext == SXTW)) ? 'w' : 'x'; - - unsigned rm = instr->GetRm(); - if (rm == kZeroRegCode) { - AppendToOutput("%czr", reg_type); - } else { - AppendToOutput("%c%d", reg_type, rm); - } - - // Extend mode UXTX is an alias for shift mode LSL here. - if (!((ext == UXTX) && (shift == 0))) { - AppendToOutput(", %s", extend_mode[ext]); - if (shift != 0) { - AppendToOutput(" #%d", instr->GetSizeLS()); - } - } - return 9; -} - - -int Disassembler::SubstitutePrefetchField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'p'); - USE(format); - - bool is_sve = - (strncmp(format, "prefSVEOp", strlen("prefSVEOp")) == 0) ? true : false; - int placeholder_length = is_sve ? 9 : 6; - static const char *stream_options[] = {"keep", "strm"}; - - auto get_hints = [](bool want_sve_hint) -> std::vector { - static const std::vector sve_hints = {"ld", "st"}; - static const std::vector core_hints = {"ld", "li", "st"}; - return (want_sve_hint) ? sve_hints : core_hints; - }; - - std::vector hints = get_hints(is_sve); - unsigned hint = - is_sve ? instr->GetSVEPrefetchHint() : instr->GetPrefetchHint(); - unsigned target = instr->GetPrefetchTarget() + 1; - unsigned stream = instr->GetPrefetchStream(); - - if ((hint >= hints.size()) || (target > 3)) { - // Unallocated prefetch operations. - if (is_sve) { - std::bitset<4> prefetch_mode(instr->GetSVEImmPrefetchOperation()); - AppendToOutput("#0b%s", prefetch_mode.to_string().c_str()); - } else { - std::bitset<5> prefetch_mode(instr->GetImmPrefetchOperation()); - AppendToOutput("#0b%s", prefetch_mode.to_string().c_str()); - } - } else { - VIXL_ASSERT(stream < ArrayLength(stream_options)); - AppendToOutput("p%sl%d%s", - hints[hint].c_str(), - target, - stream_options[stream]); - } - return placeholder_length; -} - -int Disassembler::SubstituteBarrierField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'M'); - USE(format); - - static const char *options[4][4] = {{"sy (0b0000)", "oshld", "oshst", "osh"}, - {"sy (0b0100)", "nshld", "nshst", "nsh"}, - {"sy (0b1000)", "ishld", "ishst", "ish"}, - {"sy (0b1100)", "ld", "st", "sy"}}; - int domain = instr->GetImmBarrierDomain(); - int type = instr->GetImmBarrierType(); - - AppendToOutput("%s", options[domain][type]); - return 1; -} - -int Disassembler::SubstituteSysOpField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'G'); - int op = -1; - switch (format[1]) { - case '1': - op = instr->GetSysOp1(); - break; - case '2': - op = instr->GetSysOp2(); - break; - default: - VIXL_UNREACHABLE(); - } - AppendToOutput("#%d", op); - return 2; -} - -int Disassembler::SubstituteCrField(const Instruction *instr, - const char *format) { - VIXL_ASSERT(format[0] == 'K'); - int cr = -1; - switch (format[1]) { - case 'n': - cr = instr->GetCRn(); - break; - case 'm': - cr = instr->GetCRm(); - break; - default: - VIXL_UNREACHABLE(); - } - AppendToOutput("C%d", cr); - return 2; + return {bits, off}; } int Disassembler::SubstituteIntField(const Instruction *instr, const char *format) { - VIXL_ASSERT((format[0] == 'u') || (format[0] == 's')); + VIXL_ASSERT((*format == 'u') || (*format == 's') || (*format == 'x')); // A generic signed or unsigned int field uses a placeholder of the form // 'sAABB and 'uAABB respectively where AA and BB are two digit bit positions @@ -7440,128 +4112,338 @@ int Disassembler::SubstituteIntField(const Instruction *instr, // decimal integer represented by the bits in the instruction between // positions AA and BB inclusive. // - // In addition, split fields can be represented using 'sAABB:CCDD, where CCDD + // In addition, split fields can be represented using 'sAABB_CCDD, where CCDD // become the least-significant bits of the result, and bit AA is the sign bit // (if 's is used). - int32_t bits = 0; - int width = 0; - const char *c = format; - do { - c++; // Skip the 'u', 's' or ':'. - VIXL_ASSERT(strspn(c, "0123456789") == 4); - int msb = ((c[0] - '0') * 10) + (c[1] - '0'); - int lsb = ((c[2] - '0') * 10) + (c[3] - '0'); - c += 4; // Skip the characters we just read. - int chunk_width = msb - lsb + 1; - VIXL_ASSERT((chunk_width > 0) && (chunk_width < 32)); - bits = (bits << chunk_width) | (instr->ExtractBits(msb, lsb)); - width += chunk_width; - } while (*c == ':'); - VIXL_ASSERT(IsUintN(width, bits)); - - if (format[0] == 's') { - bits = ExtractSignedBitfield32(width - 1, 0, bits); - } - - if (*c == '+') { - // A "+n" trailing the format specifier indicates the extracted value should - // be incremented by n. This is for cases where the encoding is zero-based, - // but range of values is not, eg. values [1, 16] encoded as [0, 15] - char *new_c; - uint64_t value = strtoul(c + 1, &new_c, 10); - c = new_c; - VIXL_ASSERT(IsInt32(value)); - bits = static_cast(bits + value); - } else if (*c == '*') { - // Similarly, a "*n" trailing the format specifier indicates the extracted - // value should be multiplied by n. This is for cases where the encoded - // immediate is scaled, for example by access size. - char *new_c; - uint64_t value = strtoul(c + 1, &new_c, 10); - c = new_c; - VIXL_ASSERT(IsInt32(value)); - bits = static_cast(bits * value); - } - - AppendToOutput("%d", bits); - - return static_cast(c - format); + // + // For unsigned fields, 'u may be replaced with 'x to substitute the + // hexadecimal representation instead of a decimal. + auto [bits, advance] = ExtractIntTerm(instr, format); + AppendToOutput(format[0] == 'x' ? "%x" : "%d", bits); + return advance; } -int Disassembler::SubstituteSVESize(const Instruction *instr, +int Disassembler::SubstituteFPField(const Instruction *instr, const char *format) { - USE(format); - VIXL_ASSERT(format[0] == 't'); + VIXL_ASSERT(format[0] == 'f'); + // A generic floating-point field uses a placeholder of the form 'fAABB where + // AA and BB are two-digit bit positions between 00 and 31, and AA >= BB. The + // placeholder is substituted with the 8-bit extracted integer and floating + // point value resulting from the conversion of those eight bits to FP format + // using Imm8ToFP32(). + // + // In addition, split fields can be represented using 'fAABB_CCDD, where CCDD + // become the least-significant bits of the 8-bit value. + auto [bits, advance] = ExtractIntTerm(instr, format); + AppendToOutput("0x%" PRIx32 " (%.4f)", bits, Instruction::Imm8ToFP32(bits)); + return advance; +} - static const char sizes[] = {'b', 'h', 's', 'd', 'q'}; - unsigned size_in_bytes_log2 = instr->GetSVESize(); - int placeholder_length = 1; - switch (format[1]) { - case 'f': // 'tf - FP size encoded in <18:17> - placeholder_length++; - size_in_bytes_log2 = instr->ExtractBits(18, 17); - break; - case 'l': - placeholder_length++; - if (format[2] == 's') { - // 'tls: Loads and stores - size_in_bytes_log2 = instr->ExtractBits(22, 21); - placeholder_length++; - if (format[3] == 's') { - // Sign extension load. - unsigned msize = instr->ExtractBits(24, 23); - if (msize > size_in_bytes_log2) size_in_bytes_log2 ^= 0x3; - placeholder_length++; - } - } else { - // 'tl: Logical operations - size_in_bytes_log2 = instr->GetSVEBitwiseImmLaneSizeInBytesLog2(); - } - break; - case 'm': // 'tmsz - VIXL_ASSERT(strncmp(format, "tmsz", 4) == 0); - placeholder_length += 3; - size_in_bytes_log2 = instr->ExtractBits(24, 23); - break; - case 'i': { // 'ti: indices. - std::pair index_and_lane_size = - instr->GetSVEPermuteIndexAndLaneSizeLog2(); - placeholder_length++; - size_in_bytes_log2 = index_and_lane_size.second; - break; - } - case 's': - if (format[2] == 'z') { - VIXL_ASSERT((format[3] == 'p') || (format[3] == 's') || - (format[3] == 'd')); - bool is_predicated = (format[3] == 'p'); - std::pair shift_and_lane_size = - instr->GetSVEImmShiftAndLaneSizeLog2(is_predicated); - size_in_bytes_log2 = shift_and_lane_size.second; - if (format[3] == 'd') { // Double size lanes. - size_in_bytes_log2++; - } - placeholder_length += 3; // skip "sz(p|s|d)" - } - break; - case 'h': - // Half size of the lane size field. - size_in_bytes_log2 -= 1; - placeholder_length++; - break; - case 'q': - // Quarter size of the lane size field. - size_in_bytes_log2 -= 2; - placeholder_length++; - break; - default: - break; +int Disassembler::SubstituteGenericHash(const Instruction *instr, + const char *format) { + VIXL_ASSERT(format[0] == '{'); + const char *close = strchr(format, '}'); + VIXL_ASSERT(close != nullptr); + int keylen = static_cast(close - format - 1); + std::string key(format, 1, keylen); + + struct SubstList { + std::vector bit_positions; + std::map substitutions; + std::string no_substitution; + }; + + // clang-format off + static const std::map subst = { + {"dcop", {{18, 17, 16, 11, 10, 9, 8, 7, 6, 5}, { + {0b011'0100'001, "zva"}, + {0b011'0100'011, "gva"}, + {0b011'0100'100, "gzva"}, + {0b011'1010'001, "cvac"}, + {0b011'1010'011, "cgvac"}, + {0b011'1010'101, "cgdvac"}, + {0b011'1011'001, "cvau"}, + {0b011'1100'001, "cvap"}, + {0b011'1100'011, "cgvap"}, + {0b011'1100'101, "cgdvap"}, + {0b011'1101'001, "cvadp"}, + {0b011'1110'001, "civac"}, + {0b011'1110'011, "cigvac"}, + {0b011'1110'101, "cigdvac"}, + }, "undefined"} + }, + {"pstatefield", {{18, 17, 16, 7, 6, 5}, { + {0b011'110, "daifset"}, + {0b011'111, "daifclr"}, + }, "undefined"} + } + }; + // clang-format on + + VIXL_ASSERT(subst.count(key) == 1); + auto x = subst.at(key); + int index = 0; + for (auto b : x.bit_positions) { + index <<= 1; + index |= instr->ExtractBit(b); + } + if (x.substitutions.count(index) == 1) { + AppendToOutput("%s", x.substitutions.at(index).c_str()); + } else { + AppendToOutput("%s", x.no_substitution.c_str()); + } + return keylen + 2; // +2 for the braces. +} + +int Disassembler::SubstituteGenericArray(const Instruction *instr, + const char *format) { + VIXL_ASSERT(format[0] == '['); + const char *close = strchr(format, ']'); + VIXL_ASSERT(close != nullptr); + int keylen = static_cast(close - format - 1); + std::string key(format, 1, keylen); + + struct SubstList { + std::vector bit_positions; + std::vector substitutions; + }; + + // clang-format off + static const std::map subst = { + {"ext", {{15, 14, 13}, + {"uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"}}}, + {"ext32", {{15, 14, 13}, + {"uxtb", "uxth", "lsl", "uxtx", "sxtb", "sxth", "sxtw", "sxtx"}}}, + {"ext64", {{15, 14, 13}, + {"uxtb", "uxth", "uxtw", "lsl", "sxtb", "sxth", "sxtw", "sxtx"}}}, + {"extmem", {{15, 13}, {"uxtw", "lsl", "sxtw", "sxtx"}}}, + {"cond", + {{15, 14, 13, 12}, + {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"}}}, + {"condinv", + {{15, 14, 13, 12}, + {"ne", "eq", "lo", "hs", "pl", "mi", "vc", "vs", + "ls", "hi", "lt", "ge", "le", "gt", "undefined", "undefined"}}}, + {"condb", + {{3, 2, 1, 0}, + {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", "nv"}}}, + {"nzcv", + {{3, 2, 1, 0}, + {"nzcv", "nzcV", "nzCv", "nzCV", + "nZcv", "nZcV", "nZCv", "nZCV", + "Nzcv", "NzcV", "NzCv", "NzCV", + "NZcv", "NZcV", "NZCv", "NZCV"}}}, + {"prefop", + {{4, 3, 2, 1, 0}, + {"pldl1keep", "pldl1strm", "pldl2keep", "pldl2strm", "pldl3keep", + "pldl3strm", "pldslckeep", "pldslcstrm", "plil1keep", "plil1strm", + "plil2keep", "plil2strm", "plil3keep", "plil3strm", "plislckeep", + "plislcstrm", "pstl1keep", "pstl1strm", "pstl2keep", "pstl2strm", + "pstl3keep", "pstl3strm", "pstslckeep", "pstslcstrm", "#0b11000", + "#0b11001", "#0b11010", "#0b11011", "#0b11100", "#0b11101", + "#0b11110", "#0b11111"}}}, + {"prefsveop", + {{3, 2, 1, 0}, + {"pldl1keep", "pldl1strm", "pldl2keep", "pldl2strm", + "pldl3keep", "pldl3strm", "#0b0110", "#0b0111", + "pstl1keep", "pstl1strm", "pstl2keep", "pstl2strm", + "pstl3keep", "pstl3strm", "#0b1110", "#0b1111"}}}, + {"n", {{30, 23, 22}, {"8b", "4h", "2s", "1d", "16b", "8h", "4s", "2d"}}}, + {"nl", {{23, 22}, {"8h", "4s", "2d", ""}}}, + {"nf", {{22, 30}, {"2s", "4s", "1d", "2d"}}}, + {"nload", + {{30, 11, 10}, {"8b", "4h", "2s", "1d", "16b", "8h", "4s", "2d"}}}, + {"npair", {{30, 23, 22}, {"4h", "2s", "1d", "", "8h", "4s", "2d", ""}}}, + {"nscall", {{23, 22}, {"h", "s", "d", "q"}}}, + {"nshift", + {{22, 21, 20, 19, 30}, + {"", "", "8b", "16b", "4h", "8h", "4h", "8h", "2s", "4s", "2s", + "4s", "2s", "4s", "2s", "4s", "", "2d", "", "2d", "", "2d", + "", "2d", "", "2d", "", "2d", "", "2d", "", "2d"}}}, + {"nshiftln", + {{21, 20, 19}, {"", "8h", "4s", "4s", "2d", "2d", "2d", "2d"}}}, + {"nshiftscal", + {{22, 21, 20, 19}, + {"", "b", "h", "h", "s", "s", "s", "s", + "d", "d", "d", "d", "d", "d", "d", "d"}}}, + {"sz", {{23, 22}, {"b", "h", "s", "d"}}}, + {"sszshu", + {{23, 22, 9, 8}, + {"", "b", "h", "h", "s", "s", "s", "s", + "d", "d", "d", "d", "d", "d", "d", "d"}}}, + {"sszshs", + {{23, 22, 20, 19}, + {"", "b", "h", "h", "s", "s", "s", "s", + "d", "d", "d", "d", "d", "d", "d", "d"}}}, + {"sszshd", + {{23, 22, 20, 19}, + {"", "h", "s", "s", "d", "d", "d", "d", + "", "", "", "", "", "", "", ""}}}, + {"sszld", + {{24, 23, 22, 21}, + {"b", "h", "s", "d", "d", "h", "s", "d", + "d", "s", "s", "d", "d", "s", "h", "d"}}}, + {"sszst", + {{22, 21}, + {"b", "h", "s", "d"}}}, + {"sszdup", + {{20, 19, 18, 17, 16}, + {"", "b", "h", "b", "s", "b", "h", "b", + "d", "b", "h", "b", "s", "b", "h", "b", + "q", "b", "h", "b", "s", "b", "h", "b", + "d", "b", "h", "b", "s", "b", "h", "b"}}}, + {"ntri", + {{19, 18, 17, 16, 30}, + {"", "", "8b", "16b", "4h", "8h", "8b", "16b", + "2s", "4s", "8b", "16b", "4h", "8h", "8b", "16b", + "", "2d", "8b", "16b", "4h", "8h", "8b", "16b", + "2s", "4s", "8b", "16b", "4h", "8h", "8b", "16b"}}}, + {"ntriscal", + {{19, 18, 17, 16}, + {"", "b", "h", "b", "s", "b", "h", "b", + "d", "b", "h", "b", "s", "b", "h", "b"}}}, + {"shift", {{23, 22}, {"lsl", "lsr", "asr", "ror"}}}, + {"sszlog", + {{10, 9, 8, 7, 6}, + {"s", "s", "s", "s", "s", "s", "s", "s", + "s", "s", "s", "s", "s", "s", "s", "s", + "h", "h", "h", "h", "h", "h", "h", "h", + "b", "b", "b", "b", "b", "b", "b", "",}}}, + {"sszmem", {{24, 23}, {"b", "h", "s", "d"}}}, + {"sszh", {{23, 22}, {"", "b", "h", "s"}}}, + {"sszq", {{23, 22}, {"", "", "b", "h"}}}, + {"flogbsz", {{18, 17}, {"b", "h", "s", "d"}}}, + {"mulpat", + {{9, 8, 7, 6, 5}, + {"pow2", "vl1", "vl2", "vl3", "vl4", "vl5", "vl6", + "vl7", "vl8", "vl16", "vl32", "vl64", "vl128", "vl256", + "#0xe", "#0xf", "#0x10", "#0x11", "#0x12", "#0x13", "#0x14", + "#0x15", "#0x16", "#0x17", "#0x18", "#0x19", "#0x1a", "#0x1b", + "#0x1c", "mul4", "mul3", "all"}}}, + {"barrier", + {{11, 10, 9, 8}, + {"reserved (0b0000)", "oshld", "oshst", "osh", + "reserved (0b0100)", "nshld", "nshst", "nsh", + "reserved (0b1000)", "ishld", "ishst", "ish", + "reserved (0b1100)", "ld", "st", "sy"}}}, + }; + // clang-format on + + VIXL_ASSERT(subst.count(key) == 1); + auto x = subst.at(key); + int index = 0; + for (auto b : x.bit_positions) { + index <<= 1; + index |= instr->ExtractBit(b); + } + AppendToOutput("%s", x.substitutions.at(index).c_str()); + return keylen + 2; // +2 for the braces. +} + +using ExprStack = std::stack; + +bool HandleUnaryExpression(ExprStack *s, const std::string &op) { + if (s->size() == 0) { + return false; } - VIXL_ASSERT(size_in_bytes_log2 < ArrayLength(sizes)); - AppendToOutput("%c", sizes[size_in_bytes_log2]); + uint64_t r = s->top(); + s->pop(); - return placeholder_length; + if (op == "clz32") { + s->push(CountLeadingZeros(r, 32)); + } else if (op == "ctz") { + s->push(CountTrailingZeros(r, 32)); + } else if (op == "not") { + s->push(~r); + } else if (op == "dup") { + s->push(r); + s->push(r); + } else { + s->push(r); + return false; + } + return true; +} + +bool HandleBinaryExpression(ExprStack *s, const std::string &op) { + if (s->size() < 2) { + return false; + } + + uint64_t r = s->top(); + s->pop(); + uint64_t b = s->top(); + + if (op == "+") { + r = b + r; + } else if (op == "-") { + r = b - r; + } else if (op == "*") { + r = b * r; + } else if (op == "lsl") { + r = b << r; + } else if (op == "lsr") { + r = b >> r; + } else { + s->push(r); + return false; + } + + s->pop(); + s->push(r); + return true; +} + +int Disassembler::SubstituteExpression(const Instruction *instr, + const char *format) { + USE(instr); + VIXL_ASSERT(format[0] == '<'); + const char *close = strchr(format, '>'); + VIXL_ASSERT(close != nullptr); + int exprlen = static_cast(close - format - 1); + std::string expr(format, 1, exprlen); + + ExprStack s; + std::regex re(" "); + std::sregex_token_iterator it(expr.begin(), expr.end(), re, -1); + std::sregex_token_iterator end; + + const char *placeholder = "%ld"; + for (; it != end; it++) { + std::string t = it->str(); + if (std::isdigit(t[0]) || (t[0] == 's') || (t[0] == 'u')) { + auto [value, advance] = ExtractIntTerm(instr, t.c_str()); + VIXL_ASSERT(t.length() == static_cast(advance)); + s.push(value); + } else if (HandleBinaryExpression(&s, t)) { + // Handled a binary operation - nothing else to do. + } else if (HandleUnaryExpression(&s, t)) { + // Handled a unary operation - nothing else to do. + } else if (t == "hex") { + // Print value on the stack as hexadecimal. This must be the result of the + // computation and therefore the only value on the stack. + VIXL_ASSERT(s.size() == 1); + placeholder = "%lx"; + } else { + printf("Unknown token: %s\n", t.c_str()); + VIXL_ABORT(); + } + } + VIXL_ASSERT(s.size() == 1); + AppendToOutput(placeholder, s.top()); + + return exprlen + 2; // +2 for <> +} + +int Disassembler::SubstituteEnd(const Instruction *instr, const char *format) { + USE(instr); + USE(format); + VIXL_ASSERT(format[0] == '$'); + AppendToOutput("%c", '\0'); + return 0; } int Disassembler::SubstituteTernary(const Instruction *instr, @@ -7582,12 +4464,93 @@ int Disassembler::SubstituteTernary(const Instruction *instr, return 6; } +int Disassembler::SubstituteConditionalBlock(const Instruction *instr, + const char *format) { + VIXL_ASSERT(strlen(format) >= 6); + VIXL_ASSERT((format[0] == '(') && + (format[3] == '?' || format[5] == '?' || (format[5] == '='))); + VIXL_ASSERT(strchr(format, ')') != nullptr); + + // A conditional block uses the placeholder '(AABB?xxx:yyyy)' where AA and + // BB are two digit bit positions between 00 and 31, and AA >= BB. If the + // bits of the instruction in the range AA to BB are non-zero, the placeholder + // is substituted with the string represented by xxx, else yyyy. The strings + // are of variable length and may contain other placeholders for further + // substitutions. The ':yyyy' section may be omitted, implying a zero-length + // string is substituted if instruction bits in the range AA to BB are zero. + // + // Alternatively, a specific value for the bits in the range AA to BB can + // be specified using the placeholder '(AABB=zzz?xxx:yyyy)'. If the bits in + // the range AA to BB are equal to zzz, xxx is substitued, else yyyy. As + // above, :yyyy may be omitted. + const char *c = &format[1]; + uint32_t bits = 0; + uint64_t value = 0; + bool use_explicit_value = false; + int msb = BitPositionFromString(&c[0]); + if ((format[5] == '?') || (format[5] == '=')) { // Extract a range of bits. + int lsb = BitPositionFromString(&c[2]); + bits = instr->ExtractBits(msb, lsb); + + if (format[5] == '=') { + use_explicit_value = true; + char *temp; + VIXL_ASSERT(strspn(&format[6], "0123456789") > 0); + value = strtoul(&format[6], &temp, 10); + c = temp; + } else { + c += 4; // Skip the bit positions we read above. + } + } else { + // Extract a single bit. + VIXL_ASSERT(format[3] == '?'); + bits = instr->ExtractBit(msb); + c += 2; + } + + // Skip '?' + VIXL_ASSERT(*c == '?'); + c++; + + char temp[256] = {0}; + const char *close = strchr(format, ')'); + size_t subst_len = close - c; + VIXL_ASSERT(subst_len < sizeof(temp)); + + // Copy the substitution string into a temporary buffer and set up pointers + // for the left-hand (true) and right-hand (false) sides. + memcpy(temp, c, subst_len); + + char *lhs = temp; + char *rhs = nullptr; + char *colon = strchr(temp, ':'); + if (colon != nullptr) { + // If there's a colon, set it to zero to act as the terminator for the + // left-hand string. + *colon = 0; + rhs = colon + 1; + } + + bool use_lhs; + if (use_explicit_value) { + use_lhs = (bits == value); + } else { + use_lhs = (bits != 0); + } + + char *subst = use_lhs ? lhs : rhs; + if ((subst != nullptr) && (strlen(subst) > 0)) { + Substitute(instr, subst); + } + + return static_cast(1 + close - format); +} + void Disassembler::ResetOutput() { buffer_pos_ = 0; buffer_[buffer_pos_] = 0; } - void Disassembler::AppendToOutput(const char *format, ...) { va_list args; va_start(args, format); @@ -7598,7 +4561,6 @@ void Disassembler::AppendToOutput(const char *format, ...) { va_end(args); } - void PrintDisassembler::Disassemble(const Instruction *instr) { Decoder decoder; if (cpu_features_auditor_ != NULL) { @@ -7623,7 +4585,6 @@ void PrintDisassembler::DisassembleBuffer(const Instruction *start, DisassembleBuffer(start, start + size); } - void PrintDisassembler::ProcessOutput(const Instruction *instr) { int64_t address = CodeRelativeAddress(instr); diff --git a/3rdparty/vixl/src/aarch64/instructions-aarch64.cc b/3rdparty/vixl/src/aarch64/instructions-aarch64.cc index 2ac3bcaca0..adef87f440 100644 --- a/3rdparty/vixl/src/aarch64/instructions-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/instructions-aarch64.cc @@ -603,6 +603,28 @@ std::pair Instruction::GetSVEMulLongZmAndIndex() const { return std::make_pair(reg_code, index); } +// Get the register and index for NEON indexed multiplies. +std::pair Instruction::GetNEONMulRmAndIndex() const { + int reg_code = GetRm(); + int index = (GetNEONH() << 2) | (GetNEONL() << 1) | GetNEONM(); + switch (GetNEONSize()) { + case 0: // FP H-sized elements. + case 1: // Integer H-sized elements. + // 4-bit Rm, 3-bit index. + reg_code &= 0xf; + break; + case 2: // S-sized elements. + // 5-bit Rm, 2-bit index. + index >>= 1; + break; + case 3: // FP D-sized elements. + // 5-bit Rm, 1-bit index. + index >>= 2; + break; + } + return std::make_pair(reg_code, index); +} + // Logical immediates can't encode zero, so a return value of zero is used to // indicate a failure case. Specifically, where the constraints on imm_s are // not met. @@ -1025,6 +1047,8 @@ VectorFormat VectorFormatHalfWidth(VectorFormat vform) { return kFormatVnH; case kFormatVnD: return kFormatVnS; + case kFormatVnQ: + return kFormatVnD; default: VIXL_UNREACHABLE(); return kFormatUndefined; diff --git a/3rdparty/vixl/src/aarch64/logic-aarch64.cc b/3rdparty/vixl/src/aarch64/logic-aarch64.cc index 246ffe9c58..0e268b9525 100644 --- a/3rdparty/vixl/src/aarch64/logic-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/logic-aarch64.cc @@ -6118,6 +6118,42 @@ LogicVRegister Simulator::fcvtxn2(VectorFormat vform, return dst; } +LogicVRegister Simulator::bfcvtn(VectorFormat vform, + LogicVRegister dst, + const LogicVRegister& src) { + SimVRegister tmp; + LogicVRegister srctmp = mov(kFormatVnD, tmp, src); + int input_lane_count = LaneCountFromFormat(vform); + if (IsSVEFormat(vform)) { + input_lane_count /= 2; + } + + dst.ClearForWrite(vform); + VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kHRegSize); + + for (int i = 0; i < input_lane_count; i++) { + dst.SetFloat(i, + BFloat16ToRawbits(FPToBFloat16(srctmp.Float(i), + FPTieEven, + ReadDN()))); + } + return dst; +} + +LogicVRegister Simulator::bfcvtn2(VectorFormat vform, + LogicVRegister dst, + const LogicVRegister& src) { + VIXL_ASSERT(LaneSizeInBitsFromFormat(vform) == kHRegSize); + dst.ClearForWrite(vform); + int lane_count = LaneCountFromFormat(vform) / 2; + for (int i = lane_count - 1; i >= 0; i--) { + dst.SetFloat(i + lane_count, + BFloat16ToRawbits( + FPToBFloat16(src.Float(i), FPTieEven, ReadDN()))); + } + return dst; +} + // Based on reference C function recip_sqrt_estimate from ARM ARM. double Simulator::recip_sqrt_estimate(double a) { @@ -7853,16 +7889,26 @@ LogicVRegister Simulator::matmul(VectorFormat vform_dst, // // Are stored in the input vector registers as: // -// 3 2 1 0 -// src1 = [ d | c | b | a ] -// src2 = [ D | B | C | A ] +// 3 2 1 0 +// src1 = [ d | c | b | a ] +// src2 = [ D | B | C | A ] nb. transposition // +// Giving: +// 3 2 1 0 +// result = [ w | z | y | x ] +// +// Where: +// +// x = (a * A) + (b * C) + a +// y = (a * B) + (b * D) + b +// z = (c * A) + (d * C) + c +// w = (c * B) + (d * D) + d template LogicVRegister Simulator::fmatmul(VectorFormat vform, LogicVRegister srcdst, const LogicVRegister& src1, const LogicVRegister& src2) { - T result[kZRegMaxSizeInBytes / sizeof(T)]; + T result[kZRegMaxSizeInBytes / sizeof(T)] = {}; int T_per_segment = 4; int segment_count = GetVectorLengthInBytes() / (T_per_segment * sizeof(T)); for (int seg = 0; seg < segment_count; seg++) { @@ -7879,12 +7925,9 @@ LogicVRegister Simulator::fmatmul(VectorFormat vform, } } for (int i = 0; i < LaneCountFromFormat(vform); i++) { - // Elements outside a multiple of 4T are set to zero. This happens only - // for double precision operations, when the VL is a multiple of 128 bits, - // but not a multiple of 256 bits. - T value = (i < (T_per_segment * segment_count)) ? result[i] : 0; - srcdst.SetFloat(vform, i, value); + srcdst.SetFloat(vform, i, result[i]); } + return srcdst; } @@ -8477,6 +8520,77 @@ LogicVRegister Simulator::sm3tt2(LogicVRegister srcdst, return srcdst; } +static uint64_t SM4SBox(uint64_t x) { + static const uint8_t sbox[256] = { + 0x48, 0x39, 0xcb, 0xd7, 0x3e, 0x5f, 0xee, 0x79, 0x20, 0x4d, 0xdc, 0x3a, + 0xec, 0x7d, 0xf0, 0x18, 0x84, 0xc6, 0x6e, 0xc5, 0x09, 0xf1, 0xb9, 0x65, + 0x7e, 0x77, 0x96, 0x0c, 0x4a, 0x97, 0x69, 0x89, 0xb0, 0xb4, 0xe5, 0xb8, + 0x12, 0xd0, 0x74, 0x2d, 0xbd, 0x7b, 0xcd, 0xa5, 0x88, 0x31, 0xc1, 0x0a, + 0xd8, 0x5a, 0x10, 0x1f, 0x41, 0x5c, 0xd9, 0x11, 0x7f, 0xbc, 0xdd, 0xbb, + 0x92, 0xaf, 0x1b, 0x8d, 0x51, 0x5b, 0x6c, 0x6d, 0x72, 0x6a, 0xff, 0x03, + 0x2f, 0x8e, 0xfd, 0xde, 0x45, 0x37, 0xdb, 0xd5, 0x6f, 0x4e, 0x53, 0x0d, + 0xab, 0x23, 0x29, 0xc0, 0x60, 0xca, 0x66, 0x82, 0x2e, 0xe2, 0xf6, 0x1d, + 0xe3, 0xb1, 0x8c, 0xf5, 0x30, 0x32, 0x93, 0xad, 0x55, 0x1a, 0x34, 0x9b, + 0xa4, 0x5d, 0xae, 0xe0, 0xa1, 0x15, 0x61, 0xf9, 0xce, 0xf2, 0xf7, 0xa3, + 0xb5, 0x38, 0xc7, 0x40, 0xd2, 0x8a, 0xbf, 0xea, 0x9e, 0xc8, 0xc4, 0xa0, + 0xe7, 0x02, 0x36, 0x4c, 0x52, 0x27, 0xd3, 0x9f, 0x57, 0x46, 0x00, 0xd4, + 0x87, 0x78, 0x21, 0x01, 0x3b, 0x7c, 0x22, 0x25, 0xa2, 0xd1, 0x58, 0x63, + 0x5e, 0x0e, 0x24, 0x1e, 0x35, 0x9d, 0x56, 0x70, 0x4b, 0x0f, 0xeb, 0xf8, + 0x8b, 0xda, 0x64, 0x71, 0xb2, 0x81, 0x6b, 0x68, 0xa8, 0x4f, 0x85, 0xe6, + 0x19, 0x3c, 0x59, 0x83, 0xba, 0x17, 0x73, 0xf3, 0xfc, 0xa7, 0x07, 0x47, + 0xa6, 0x3f, 0x8f, 0x75, 0xfa, 0x94, 0xdf, 0x80, 0x95, 0xe8, 0x08, 0xc9, + 0xa9, 0x1c, 0xb3, 0xe4, 0x62, 0xac, 0xcf, 0xed, 0x43, 0x0b, 0x54, 0x33, + 0x7a, 0x98, 0xef, 0x91, 0xf4, 0x50, 0x42, 0x9c, 0x99, 0x06, 0x86, 0x49, + 0x26, 0x13, 0x44, 0xaa, 0xc3, 0x04, 0xbe, 0x2a, 0x76, 0x9a, 0x67, 0x2b, + 0x05, 0x2c, 0xfb, 0x28, 0xc2, 0x14, 0xb6, 0x16, 0xb7, 0x3d, 0xe1, 0xcc, + 0xfe, 0xe9, 0x90, 0xd6, + }; + uint64_t result = 0; + for (int j = 24; j >= 0; j -= 8) { + uint8_t s = 255 - ((x >> j) & 0xff); + result = (result << 8) | sbox[s]; + } + return result; +} + +LogicVRegister Simulator::sm4(LogicVRegister srcdst, + const LogicVRegister& src1, + const LogicVRegister& src2, + bool is_key) { + using namespace std::placeholders; + auto ROL = std::bind(RotateLeft, _1, _2, kSRegSize); + + VectorFormat vf = kFormat4S; + uint64_t result[4] = {}; + if (is_key) { + src1.UintArray(vf, result); + } else { + srcdst.UintArray(vf, result); + } + + for (int i = 0; i < 4; i++) { + uint64_t k = is_key ? src2.Uint(vf, i) : src1.Uint(vf, i); + uint64_t intval = result[3] ^ result[2] ^ result[1] ^ k; + intval = SM4SBox(intval); + + if (is_key) { + intval ^= ROL(intval, 13) ^ ROL(intval, 23); + } else { + intval ^= + ROL(intval, 2) ^ ROL(intval, 10) ^ ROL(intval, 18) ^ ROL(intval, 24); + } + + intval ^= result[0]; + + result[0] = result[1]; + result[1] = result[2]; + result[2] = result[3]; + result[3] = intval; + } + srcdst.SetUintArray(vf, result); + return srcdst; +} + } // namespace aarch64 } // namespace vixl diff --git a/3rdparty/vixl/src/aarch64/macro-assembler-aarch64.cc b/3rdparty/vixl/src/aarch64/macro-assembler-aarch64.cc index af90a4237f..69adb11df8 100644 --- a/3rdparty/vixl/src/aarch64/macro-assembler-aarch64.cc +++ b/3rdparty/vixl/src/aarch64/macro-assembler-aarch64.cc @@ -550,8 +550,7 @@ void MacroAssembler::B(Label* label) { b(label); } - -void MacroAssembler::B(Label* label, Condition cond) { +void MacroAssembler::Bcommon(Label* label, Condition cond, bool use_bc) { // We don't need to check the size of the literal pool, because the size of // the literal pool is already bounded by the literal range, which is smaller // than the range of this branch. @@ -563,7 +562,11 @@ void MacroAssembler::B(Label* label, Condition cond) { if (label->IsBound() && LabelIsOutOfRange(label, CondBranchType)) { Label done; - b(&done, InvertCondition(cond)); + if (use_bc) { + bc(&done, InvertCondition(cond)); + } else { + b(&done, InvertCondition(cond)); + } b(label); bind(&done); } else { @@ -572,7 +575,11 @@ void MacroAssembler::B(Label* label, Condition cond) { label, CondBranchType); } - b(label, cond); + if (use_bc) { + bc(label, cond); + } else { + b(label, cond); + } } } diff --git a/3rdparty/vixl/src/aarch64/simulator-aarch64.cc b/3rdparty/vixl/src/aarch64/simulator-aarch64.cc new file mode 100644 index 0000000000..ee11b642b5 --- /dev/null +++ b/3rdparty/vixl/src/aarch64/simulator-aarch64.cc @@ -0,0 +1,15385 @@ +// Copyright 2015, VIXL authors +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of ARM Limited nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND +// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64 + +#include "simulator-aarch64.h" + +#include +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#undef MultiplyHigh +#include +#else +#include +#include +#endif + +#ifdef _MSC_VER +#define VIXL_SYNC() MemoryBarrier() +#else +#define VIXL_SYNC() __sync_synchronize() +#endif + +namespace vixl { +namespace aarch64 { + +using vixl::internal::SimFloat16; + +const Instruction* Simulator::kEndOfSimAddress = NULL; + +MemoryAccessResult TryMemoryAccess(uintptr_t address, uintptr_t access_size) { +#ifdef VIXL_ENABLE_IMPLICIT_CHECKS + for (uintptr_t i = 0; i < access_size; i++) { + if (_vixl_internal_ReadMemory(address, i) == MemoryAccessResult::Failure) { + // The memory access failed. + return MemoryAccessResult::Failure; + } + } + + // Either the memory access did not raise a signal or the signal handler did + // not correctly return MemoryAccessResult::Failure. + return MemoryAccessResult::Success; +#else + USE(address); + USE(access_size); + return MemoryAccessResult::Success; +#endif // VIXL_ENABLE_IMPLICIT_CHECKS +} + +bool MetaDataDepot::MetaDataMTE::is_active = false; + +void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) { + int width = msb - lsb + 1; + VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits)); + + bits <<= lsb; + uint32_t mask = ((1 << width) - 1) << lsb; + VIXL_ASSERT((mask & write_ignore_mask_) == 0); + + value_ = (value_ & ~mask) | (bits & mask); +} + + +SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) { + switch (id) { + case NZCV: + return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask); + case FPCR: + return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask); + default: + VIXL_UNREACHABLE(); + return SimSystemRegister(); + } +} + +const Simulator::FormToVisitorFnMap* Simulator::GetFormToVisitorFnMap() { + static const FormToVisitorFnMap form_to_visitor = { + DEFAULT_FORM_TO_VISITOR_MAP(Simulator), + SIM_AUD_VISITOR_MAP(Simulator), + {"fmov_h_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fmov_s_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fmov_d_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_ds_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_sd_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_hs_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_sh_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_dh_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"fcvt_hd_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"bfcvt_bs_floatdp1"_h, &Simulator::SimulateFPConvert}, + {"frint32x_d_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint32x_s_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint32z_d_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint32z_s_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint64x_d_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint64x_s_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint64z_d_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frint64z_s_floatdp1"_h, &Simulator::SimulateFPRoundIntToSize}, + {"frinta_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frinta_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frinta_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frinti_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frinti_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frinti_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintm_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintm_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintm_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintn_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintn_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintn_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintp_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintp_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintp_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintx_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintx_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintx_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintz_d_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintz_h_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"frintz_s_floatdp1"_h, &Simulator::SimulateFPRoundInt}, + {"fcvtas_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtau_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtl_asimdmisc_l"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtms_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtmu_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtns_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtnu_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtn_asimdmisc_n"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtps_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtpu_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtxn_asimdmisc_n"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtzs_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"fcvtzu_asimdmisc_r"_h, &Simulator::SimulateNEONFPConvert}, + {"bfcvtn_asimdmisc_4s"_h, &Simulator::SimulateNEONFPConvert}, + {"frint32x_asimdmisc_r"_h, &Simulator::SimulateNEONRoundIntToSize}, + {"frint32z_asimdmisc_r"_h, &Simulator::SimulateNEONRoundIntToSize}, + {"frint64x_asimdmisc_r"_h, &Simulator::SimulateNEONRoundIntToSize}, + {"frint64z_asimdmisc_r"_h, &Simulator::SimulateNEONRoundIntToSize}, + {"frinta_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frinti_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frintm_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frintn_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frintp_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frintx_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"frintz_asimdmisc_r"_h, &Simulator::SimulateNEONRoundInt}, + {"fabs_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fcmeq_asimdmisc_fz"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fcmge_asimdmisc_fz"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fcmgt_asimdmisc_fz"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fcmle_asimdmisc_fz"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fcmlt_asimdmisc_fz"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fneg_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"frecpe_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"frsqrte_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"fsqrt_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"scvtf_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"ucvtf_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"urecpe_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"ursqrte_asimdmisc_r"_h, &Simulator::SimulateNEONFP2RegMisc}, + {"smlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"smlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"smull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"sqdmlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"sqdmlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"sqdmull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"umlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"umlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"umull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong}, + {"fcmla_asimdelem_c_h"_h, &Simulator::SimulateNEONComplexMulByElement}, + {"fcmla_asimdelem_c_s"_h, &Simulator::SimulateNEONComplexMulByElement}, + {"fmlal2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong}, + {"fmlal_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong}, + {"fmlsl2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong}, + {"fmlsl_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong}, + {"fmla_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmls_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmulx_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmul_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmla_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmls_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmulx_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement}, + {"fmul_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement}, + {"sdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement}, + {"udot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement}, + {"adclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry}, + {"adclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry}, + {"addhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"addhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"addp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair}, + {"bcax_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"bdep_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"bext_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"bgrp_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"bsl1n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"bsl2n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"bsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"cadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const}, + {"cdot_z_zzz"_h, &Simulator::SimulateSVEComplexDotProduct}, + {"cdot_z_zzzi_d"_h, &Simulator::SimulateSVEComplexDotProduct}, + {"cdot_z_zzzi_s"_h, &Simulator::SimulateSVEComplexDotProduct}, + {"cmla_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"cmla_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"cmla_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"eor3_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"eorbt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"eortb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"ext_z_zi_con"_h, &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm}, + {"faddp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT}, + {"fcvtlt_z_p_z_h2s"_h, &Simulator::SimulateSVEFPConvertLong}, + {"fcvtlt_z_p_z_s2d"_h, &Simulator::SimulateSVEFPConvertLong}, + {"fcvtnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD}, + {"bfcvt_z_p_z_s2bf"_h, &Simulator::Simulate_ZdH_PgM_ZnS}, + {"bfcvtnt_z_p_z_s2bf"_h, &Simulator::Simulate_ZdH_PgM_ZnS}, + {"fcvtnt_z_p_z_s2h"_h, &Simulator::Simulate_ZdH_PgM_ZnS}, + {"fcvtx_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD}, + {"fcvtxnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD}, + {"flogb_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT}, + {"fmaxnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT}, + {"fmaxp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT}, + {"fminnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT}, + {"fminp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT}, + {"fmlalb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH}, + {"fmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"fmlalt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH}, + {"fmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"fmlslb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH}, + {"fmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"fmlslt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH}, + {"fmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"histcnt_z_p_zz"_h, &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT}, + {"histseg_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB}, + {"ldnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm}, + {"ldnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm}, + {"ldnt1sb_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1sb_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm}, + {"ldnt1sh_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1sh_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm}, + {"ldnt1sw_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm}, + {"ldnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm}, + {"match_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT}, + {"mla_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mla_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mla_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mls_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mls_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mls_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex}, + {"mul_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"mul_z_zzi_d"_h, &Simulator::SimulateSVEMulIndex}, + {"mul_z_zzi_h"_h, &Simulator::SimulateSVEMulIndex}, + {"mul_z_zzi_s"_h, &Simulator::SimulateSVEMulIndex}, + {"nbsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary}, + {"nmatch_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT}, + {"pmul_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB}, + {"pmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"pmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"raddhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"raddhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"rshrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"rshrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"rsubhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"rsubhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"saba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT}, + {"sabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"sabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"sabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"sabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"sadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb}, + {"saddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"saddlbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"saddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"saddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"saddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"sbclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry}, + {"sbclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry}, + {"shadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"shrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"shrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"shsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"shsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"sli_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const}, + {"smaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair}, + {"sminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair}, + {"smlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"smlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"smlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"smlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"smlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"smullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"smullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"smullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"smullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"splice_z_p_zz_con"_h, &Simulator::VisitSVEVectorSplice}, + {"sqabs_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT}, + {"sqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"sqcadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const}, + {"sqdmlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlalb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm}, + {"sqdmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"sqdmlalbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlalt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm}, + {"sqdmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"sqdmlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlslb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm}, + {"sqdmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"sqdmlslbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"sqdmlslt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm}, + {"sqdmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm}, + {"sqdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"sqdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqdmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"sqdmullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"sqdmullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"sqdmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"sqdmullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"sqdmullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"sqneg_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT}, + {"sqrdcmlah_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"sqrdcmlah_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"sqrdcmlah_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd}, + {"sqrdmlah_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlah_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlah_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlah_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlsh_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlsh_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlsh_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmlsh_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh}, + {"sqrdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"sqrdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqrdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqrdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex}, + {"sqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"sqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"sqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqrshrunb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqrshrunt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const}, + {"sqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"sqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"sqshlu_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const}, + {"sqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqshrunb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqshrunt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"sqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"sqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"sqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"sqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"sqxtunb_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"sqxtunt_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"srhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"sri_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const}, + {"srshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"srshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"srshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const}, + {"srsra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const}, + {"sshllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm}, + {"sshllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm}, + {"ssra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const}, + {"ssublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"ssublbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"ssublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"ssubltb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"ssubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"ssubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"stnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm}, + {"stnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm}, + {"stnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm}, + {"stnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm}, + {"stnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm}, + {"stnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm}, + {"stnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm}, + {"subhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"subhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh}, + {"suqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"tbl_z_zz_2"_h, &Simulator::VisitSVETableLookup}, + {"tbx_z_zz"_h, &Simulator::VisitSVETableLookup}, + {"uaba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT}, + {"uabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb}, + {"uaddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uaddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"uaddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"uaddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"uhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"uhsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"uhsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"umaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair}, + {"uminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair}, + {"umlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"umlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"umlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"umlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb}, + {"umlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT}, + {"umullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"umullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec}, + {"umullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"umullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx}, + {"uqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"uqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"uqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"uqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"uqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"uqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const}, + {"uqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"uqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"uqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"uqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow}, + {"uqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"uqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"uqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"uqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow}, + {"urecpe_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS}, + {"urhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub}, + {"urshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"urshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated}, + {"urshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const}, + {"ursqrte_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS}, + {"ursra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const}, + {"ushllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm}, + {"ushllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm}, + {"usqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic}, + {"usra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const}, + {"usublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"usublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong}, + {"usubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"usubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb}, + {"whilege_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit}, + {"whilegt_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit}, + {"whilehi_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit}, + {"whilehs_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit}, + {"whilerw_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm}, + {"whilewr_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm}, + {"xar_z_zzi"_h, &Simulator::SimulateSVEExclusiveOrRotate}, + {"smmla_z_zzz"_h, &Simulator::SimulateMatrixMul}, + {"ummla_z_zzz"_h, &Simulator::SimulateMatrixMul}, + {"usmmla_z_zzz"_h, &Simulator::SimulateMatrixMul}, + {"smmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul}, + {"ummla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul}, + {"usmmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul}, + {"fmmla_z_zzz_s"_h, &Simulator::SimulateSVEFPMatrixMul}, + {"fmmla_z_zzz_d"_h, &Simulator::SimulateSVEFPMatrixMul}, + {"ld1row_z_p_bi_u32"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, + {"ld1row_z_p_br_contiguous"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, + {"ld1rod_z_p_bi_u64"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, + {"ld1rod_z_p_br_contiguous"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, + {"ld1rob_z_p_bi_u8"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, + {"ld1rob_z_p_br_contiguous"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, + {"ld1roh_z_p_bi_u16"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm}, + {"ld1roh_z_p_br_contiguous"_h, + &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar}, + {"usdot_z_zzz_s"_h, &Simulator::VisitSVEIntMulAddUnpredicated}, + {"sudot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex}, + {"usdot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex}, + {"usdot_asimdsame2_d"_h, &Simulator::VisitNEON3SameExtra}, + {"sudot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement}, + {"usdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement}, + {"addg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag}, + {"gmi_64g_dp_2src"_h, &Simulator::SimulateMTETagMaskInsert}, + {"irg_64i_dp_2src"_h, &Simulator::Simulate_XdSP_XnSP_Xm}, + {"ldg_64loffset_ldsttags"_h, &Simulator::SimulateMTELoadTag}, + {"st2g_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"st2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"st2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stgp_64_ldstpair_off"_h, &Simulator::SimulateMTEStoreTagPair}, + {"stgp_64_ldstpair_post"_h, &Simulator::SimulateMTEStoreTagPair}, + {"stgp_64_ldstpair_pre"_h, &Simulator::SimulateMTEStoreTagPair}, + {"stg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stz2g_64soffset_ldsttags"_h, + &Simulator::Simulator::SimulateMTEStoreTag}, + {"stz2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stz2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stzg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stzg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"stzg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag}, + {"subg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag}, + {"subps_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer}, + {"subp_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer}, + {"cpyen_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyern_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyewn_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpye_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyfen_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyfern_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyfewn_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyfe_cpy_memcms"_h, &Simulator::SimulateCpyE}, + {"cpyfmn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpyfmrn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpyfmwn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpyfm_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpyfpn_cpy_memcms"_h, &Simulator::SimulateCpyFP}, + {"cpyfprn_cpy_memcms"_h, &Simulator::SimulateCpyFP}, + {"cpyfpwn_cpy_memcms"_h, &Simulator::SimulateCpyFP}, + {"cpyfp_cpy_memcms"_h, &Simulator::SimulateCpyFP}, + {"cpymn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpymrn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpymwn_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpym_cpy_memcms"_h, &Simulator::SimulateCpyM}, + {"cpypn_cpy_memcms"_h, &Simulator::SimulateCpyP}, + {"cpyprn_cpy_memcms"_h, &Simulator::SimulateCpyP}, + {"cpypwn_cpy_memcms"_h, &Simulator::SimulateCpyP}, + {"cpyp_cpy_memcms"_h, &Simulator::SimulateCpyP}, + {"setp_set_memcms"_h, &Simulator::SimulateSetP}, + {"setpn_set_memcms"_h, &Simulator::SimulateSetP}, + {"setgp_set_memcms"_h, &Simulator::SimulateSetGP}, + {"setgpn_set_memcms"_h, &Simulator::SimulateSetGP}, + {"setm_set_memcms"_h, &Simulator::SimulateSetM}, + {"setmn_set_memcms"_h, &Simulator::SimulateSetM}, + {"setgm_set_memcms"_h, &Simulator::SimulateSetGM}, + {"setgmn_set_memcms"_h, &Simulator::SimulateSetGM}, + {"sete_set_memcms"_h, &Simulator::SimulateSetE}, + {"seten_set_memcms"_h, &Simulator::SimulateSetE}, + {"setge_set_memcms"_h, &Simulator::SimulateSetE}, + {"setgen_set_memcms"_h, &Simulator::SimulateSetE}, + {"abs_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"abs_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"cnt_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"cnt_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"ctz_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"ctz_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source}, + {"smax_32_dp_2src"_h, &Simulator::SimulateSignedMinMax}, + {"smax_64_dp_2src"_h, &Simulator::SimulateSignedMinMax}, + {"smin_32_dp_2src"_h, &Simulator::SimulateSignedMinMax}, + {"smin_64_dp_2src"_h, &Simulator::SimulateSignedMinMax}, + {"smax_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax}, + {"smax_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax}, + {"smin_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax}, + {"smin_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax}, + {"umax_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax}, + {"umax_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax}, + {"umin_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax}, + {"umin_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax}, + {"umax_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax}, + {"umax_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax}, + {"umin_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax}, + {"umin_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax}, + {"bcax_vvv16_crypto4"_h, &Simulator::SimulateNEONSHA3}, + {"eor3_vvv16_crypto4"_h, &Simulator::SimulateNEONSHA3}, + {"rax1_vvv2_cryptosha512_3"_h, &Simulator::SimulateNEONSHA3}, + {"xar_vvv2_crypto3_imm6"_h, &Simulator::SimulateNEONSHA3}, + {"sha512h_qqv_cryptosha512_3"_h, &Simulator::SimulateSHA512}, + {"sha512h2_qqv_cryptosha512_3"_h, &Simulator::SimulateSHA512}, + {"sha512su0_vv2_cryptosha512_2"_h, &Simulator::SimulateSHA512}, + {"sha512su1_vvv2_cryptosha512_3"_h, &Simulator::SimulateSHA512}, + {"pmullb_z_zz_q"_h, &Simulator::SimulateSVEPmull128}, + {"pmullt_z_zz_q"_h, &Simulator::SimulateSVEPmull128}, + }; + return &form_to_visitor; +} + +// Try to access the piece of memory given by the address passed in RDI and the +// offset passed in RSI, using testb. If a signal is raised then the signal +// handler should set RIP to _vixl_internal_AccessMemory_continue and RAX to +// MemoryAccessResult::Failure. If no signal is raised then zero RAX before +// returning. +#ifdef VIXL_ENABLE_IMPLICIT_CHECKS +#ifdef __x86_64__ +asm(R"( + .globl _vixl_internal_ReadMemory + _vixl_internal_ReadMemory: + testb (%rdi, %rsi), %al + xorq %rax, %rax + ret + .globl _vixl_internal_AccessMemory_continue + _vixl_internal_AccessMemory_continue: + ret +)"); +#else +asm(R"( + .globl _vixl_internal_ReadMemory + _vixl_internal_ReadMemory: + ret +)"); +#endif // __x86_64__ +#endif // VIXL_ENABLE_IMPLICIT_CHECKS + +Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack) + : memory_(std::move(stack)), + last_instr_(NULL), + cpu_features_auditor_(decoder, CPUFeatures::All()), + gcs_({nullptr, kGCSNoStack}), + gcs_enabled_(false) { + // Ensure that shift operations act as the simulator expects. + VIXL_ASSERT((static_cast(-1) >> 1) == -1); + VIXL_ASSERT((static_cast(-1) >> 1) == 0x7fffffff); + + // Set up a placeholder pipe for CanReadMemory. +#ifndef _WIN32 + VIXL_CHECK(pipe(placeholder_pipe_fd_) == 0); +#endif + + // Set up the decoder. + decoder_ = decoder; + decoder_->AppendVisitor(this); + + stream_ = stream; + + print_disasm_ = new PrintDisassembler(stream_); + + memory_.AppendMetaData(&meta_data_); + + // The Simulator and Disassembler share the same available list, held by the + // auditor. The Disassembler only annotates instructions with features that + // are _not_ available, so registering the auditor should have no effect + // unless the simulator is about to abort (due to missing features). In + // practice, this means that with trace enabled, the simulator will crash just + // after the disassembler prints the instruction, with the missing features + // enumerated. + print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_); + + SetColouredTrace(false); + trace_parameters_ = LOG_NONE; + + // We have to configure the SVE vector register length before calling + // ResetState(). + SetVectorLengthInBits(kZRegMinSize); + + ResetState(); + + // Print a warning about exclusive-access instructions, but only the first + // time they are encountered. This warning can be silenced using + // SilenceExclusiveAccessWarning(). + print_exclusive_access_warning_ = true; + + guard_pages_ = false; + + // Initialize the common state of RNDR and RNDRRS. + uint64_t seed = (11 + (22 << 16) + (static_cast(33) << 32)); + rand_gen_.seed(seed); + + // Initialize all bits of pseudo predicate register to true. + LogicPRegister ones(pregister_all_true_); + ones.SetAllBits(); + + // Initialize the debugger but disable it by default. + SetDebuggerEnabled(false); + debugger_ = std::make_unique(this); +} + +void Simulator::ResetSystemRegisters() { + // Reset the system registers. + nzcv_ = SimSystemRegister::DefaultValueFor(NZCV); + fpcr_ = SimSystemRegister::DefaultValueFor(FPCR); + ResetFFR(); +} + +void Simulator::ResetRegisters() { + for (unsigned i = 0; i < kNumberOfRegisters; i++) { + WriteXRegister(i, 0xbadbeef); + } + // Returning to address 0 exits the Simulator. + WriteLr(kEndOfSimAddress); +} + +void Simulator::ResetVRegisters() { + // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP. + VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0); + int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes; + for (unsigned i = 0; i < kNumberOfZRegisters; i++) { + VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes()); + vregisters_[i].NotifyAccessAsZ(); + for (int lane = 0; lane < lane_count; lane++) { + // Encode the register number and (D-sized) lane into each NaN, to + // make them easier to trace. + uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) | + (0x0000000000000001 * lane); + VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask))); + VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask))); + vregisters_[i].Insert(lane, nan_bits); + } + } +} + +void Simulator::ResetPRegisters() { + VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0); + int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes; + // Ensure the register configuration fits in this bit encoding. + VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX); + VIXL_ASSERT(lane_count <= UINT8_MAX); + for (unsigned i = 0; i < kNumberOfPRegisters; i++) { + VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes()); + for (int lane = 0; lane < lane_count; lane++) { + // Encode the register number and (H-sized) lane into each lane slot. + uint16_t bits = (0x0100 * lane) | i; + pregisters_[i].Insert(lane, bits); + } + } +} + +void Simulator::ResetFFR() { + VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0); + int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes; + ffr_register_.Write(static_cast(GetUintMask(default_active_lanes))); +} + +void Simulator::ResetState() { + ResetSystemRegisters(); + ResetRegisters(); + ResetVRegisters(); + ResetPRegisters(); + + WriteSp(memory_.GetStack().GetBase()); + ResetGCSState(); + EnableGCSCheck(); + + pc_ = NULL; + pc_modified_ = false; + + // BTI state. + btype_ = DefaultBType; + next_btype_ = DefaultBType; + + meta_data_.ResetState(); +} + +void Simulator::SetVectorLengthInBits(unsigned vector_length) { + VIXL_ASSERT((vector_length >= kZRegMinSize) && + (vector_length <= kZRegMaxSize)); + VIXL_ASSERT(IsPowerOf2(vector_length)); + vector_length_ = vector_length; + + for (unsigned i = 0; i < kNumberOfZRegisters; i++) { + vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes()); + } + for (unsigned i = 0; i < kNumberOfPRegisters; i++) { + pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes()); + } + + ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes()); + + ResetVRegisters(); + ResetPRegisters(); + ResetFFR(); +} + +Simulator::~Simulator() { + // The decoder may outlive the simulator. + decoder_->RemoveVisitor(print_disasm_); + delete print_disasm_; +#ifndef _WIN32 + close(placeholder_pipe_fd_[0]); + close(placeholder_pipe_fd_[1]); +#endif + GetGCSManager().FreeStack(GetGCSToken()); +} + + +void Simulator::Run() { + // Flush any written registers before executing anything, so that + // manually-set registers are logged _before_ the first instruction. + LogAllWrittenRegisters(); + + if (debugger_enabled_) { + // Slow path to check for breakpoints only if the debugger is enabled. + Debugger* debugger = GetDebugger(); + while (!IsSimulationFinished()) { + if (debugger->IsAtBreakpoint()) { + fprintf(stream_, "Debugger hit breakpoint, breaking...\n"); + debugger->Debug(); + } else { + ExecuteInstruction(); + } + } + } else { + while (!IsSimulationFinished()) { + ExecuteInstruction(); + } + } +} + + +void Simulator::RunFrom(const Instruction* first) { + WritePc(first, NoBranchLog); + Run(); +} + + +// clang-format off +const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5", + "x6", "x7", "x8", "x9", "x10", "x11", + "x12", "x13", "x14", "x15", "x16", "x17", + "x18", "x19", "x20", "x21", "x22", "x23", + "x24", "x25", "x26", "x27", "x28", "x29", + "lr", "xzr", "sp"}; + +const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5", + "w6", "w7", "w8", "w9", "w10", "w11", + "w12", "w13", "w14", "w15", "w16", "w17", + "w18", "w19", "w20", "w21", "w22", "w23", + "w24", "w25", "w26", "w27", "w28", "w29", + "w30", "wzr", "wsp"}; + +const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5", + "b6", "b7", "b8", "b9", "b10", "b11", + "b12", "b13", "b14", "b15", "b16", "b17", + "b18", "b19", "b20", "b21", "b22", "b23", + "b24", "b25", "b26", "b27", "b28", "b29", + "b30", "b31"}; + +const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5", + "h6", "h7", "h8", "h9", "h10", "h11", + "h12", "h13", "h14", "h15", "h16", "h17", + "h18", "h19", "h20", "h21", "h22", "h23", + "h24", "h25", "h26", "h27", "h28", "h29", + "h30", "h31"}; + +const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5", + "s6", "s7", "s8", "s9", "s10", "s11", + "s12", "s13", "s14", "s15", "s16", "s17", + "s18", "s19", "s20", "s21", "s22", "s23", + "s24", "s25", "s26", "s27", "s28", "s29", + "s30", "s31"}; + +const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5", + "d6", "d7", "d8", "d9", "d10", "d11", + "d12", "d13", "d14", "d15", "d16", "d17", + "d18", "d19", "d20", "d21", "d22", "d23", + "d24", "d25", "d26", "d27", "d28", "d29", + "d30", "d31"}; + +const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5", + "v6", "v7", "v8", "v9", "v10", "v11", + "v12", "v13", "v14", "v15", "v16", "v17", + "v18", "v19", "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", "v28", "v29", + "v30", "v31"}; + +const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5", + "z6", "z7", "z8", "z9", "z10", "z11", + "z12", "z13", "z14", "z15", "z16", "z17", + "z18", "z19", "z20", "z21", "z22", "z23", + "z24", "z25", "z26", "z27", "z28", "z29", + "z30", "z31"}; + +const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5", + "p6", "p7", "p8", "p9", "p10", "p11", + "p12", "p13", "p14", "p15"}; +// clang-format on + + +const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { + // If the code represents the stack pointer, index the name after zr. + if ((code == kSPRegInternalCode) || + ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) { + code = kZeroRegCode + 1; + } + VIXL_ASSERT(code < ArrayLength(wreg_names)); + return wreg_names[code]; +} + + +const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { + // If the code represents the stack pointer, index the name after zr. + if ((code == kSPRegInternalCode) || + ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) { + code = kZeroRegCode + 1; + } + VIXL_ASSERT(code < ArrayLength(xreg_names)); + return xreg_names[code]; +} + + +const char* Simulator::BRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfVRegisters); + return breg_names[code]; +} + + +const char* Simulator::HRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfVRegisters); + return hreg_names[code]; +} + + +const char* Simulator::SRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfVRegisters); + return sreg_names[code]; +} + + +const char* Simulator::DRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfVRegisters); + return dreg_names[code]; +} + + +const char* Simulator::VRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfVRegisters); + return vreg_names[code]; +} + + +const char* Simulator::ZRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfZRegisters); + return zreg_names[code]; +} + + +const char* Simulator::PRegNameForCode(unsigned code) { + VIXL_ASSERT(code < kNumberOfPRegisters); + return preg_names[code]; +} + +SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) { + SimVRegister ones, result; + dup_immediate(kFormatVnB, ones, 0xff); + mov_zeroing(kFormatVnB, result, pg, ones); + return result; +} + +void Simulator::ExtractFromSimVRegister(VectorFormat vform, + SimPRegister& pd, + SimVRegister vreg) { + SimVRegister zero; + dup_immediate(kFormatVnB, zero, 0); + SVEIntCompareVectorsHelper(ne, + vform, + pd, + GetPTrue(), + vreg, + zero, + false, + LeaveFlags); +} + +#define COLOUR(colour_code) "\033[0;" colour_code "m" +#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m" +#define COLOUR_HIGHLIGHT "\033[43m" +#define NORMAL "" +#define GREY "30" +#define RED "31" +#define GREEN "32" +#define YELLOW "33" +#define BLUE "34" +#define MAGENTA "35" +#define CYAN "36" +#define WHITE "37" +void Simulator::SetColouredTrace(bool value) { + coloured_trace_ = value; + + clr_normal = value ? COLOUR(NORMAL) : ""; + clr_flag_name = value ? COLOUR_BOLD(WHITE) : ""; + clr_flag_value = value ? COLOUR(NORMAL) : ""; + clr_reg_name = value ? COLOUR_BOLD(CYAN) : ""; + clr_reg_value = value ? COLOUR(CYAN) : ""; + clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : ""; + clr_vreg_value = value ? COLOUR(MAGENTA) : ""; + clr_preg_name = value ? COLOUR_BOLD(GREEN) : ""; + clr_preg_value = value ? COLOUR(GREEN) : ""; + clr_memory_address = value ? COLOUR_BOLD(BLUE) : ""; + clr_warning = value ? COLOUR_BOLD(YELLOW) : ""; + clr_warning_message = value ? COLOUR(YELLOW) : ""; + clr_printf = value ? COLOUR(GREEN) : ""; + clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : ""; + + if (value) { + print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED)); + print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL)); + } else { + print_disasm_->SetCPUFeaturesPrefix("// Needs: "); + print_disasm_->SetCPUFeaturesSuffix(""); + } +} + + +void Simulator::SetTraceParameters(int parameters) { + bool disasm_before = trace_parameters_ & LOG_DISASM; + trace_parameters_ = parameters; + bool disasm_after = trace_parameters_ & LOG_DISASM; + + if (disasm_before != disasm_after) { + if (disasm_after) { + decoder_->InsertVisitorBefore(print_disasm_, this); + } else { + decoder_->RemoveVisitor(print_disasm_); + } + } +} + +// Helpers --------------------------------------------------------------------- +uint64_t Simulator::AddWithCarry(unsigned reg_size, + bool set_flags, + uint64_t left, + uint64_t right, + int carry_in) { + std::pair result_and_flags = + AddWithCarry(reg_size, left, right, carry_in); + if (set_flags) { + uint8_t flags = result_and_flags.second; + ReadNzcv().SetN((flags >> 3) & 1); + ReadNzcv().SetZ((flags >> 2) & 1); + ReadNzcv().SetC((flags >> 1) & 1); + ReadNzcv().SetV((flags >> 0) & 1); + LogSystemRegister(NZCV); + } + return result_and_flags.first; +} + +std::pair Simulator::AddWithCarry(unsigned reg_size, + uint64_t left, + uint64_t right, + int carry_in) { + VIXL_ASSERT((carry_in == 0) || (carry_in == 1)); + VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize)); + + uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt; + uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask; + uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask; + + left &= reg_mask; + right &= reg_mask; + uint64_t result = (left + right + carry_in) & reg_mask; + + // NZCV bits, ordered N in bit 3 to V in bit 0. + uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0; + nzcv |= CalcZFlag(result) ? 4 : 0; + + // Compute the C flag by comparing the result to the max unsigned integer. + uint64_t max_uint_2op = max_uint - carry_in; + bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right); + nzcv |= C ? 2 : 0; + + // Overflow iff the sign bit is the same for the two inputs and different + // for the result. + uint64_t left_sign = left & sign_mask; + uint64_t right_sign = right & sign_mask; + uint64_t result_sign = result & sign_mask; + bool V = (left_sign == right_sign) && (left_sign != result_sign); + nzcv |= V ? 1 : 0; + + return std::make_pair(result, nzcv); +} + +using vixl_uint128_t = std::pair; + +vixl_uint128_t Simulator::Add128(vixl_uint128_t x, vixl_uint128_t y) { + std::pair sum_lo = + AddWithCarry(kXRegSize, x.second, y.second, 0); + int carry_in = (sum_lo.second & 0x2) >> 1; // C flag in NZCV result. + std::pair sum_hi = + AddWithCarry(kXRegSize, x.first, y.first, carry_in); + return std::make_pair(sum_hi.first, sum_lo.first); +} + +vixl_uint128_t Simulator::Lsl128(vixl_uint128_t x, unsigned shift) const { + VIXL_ASSERT(shift <= 64); + if (shift == 0) return x; + if (shift == 64) return std::make_pair(x.second, 0); + uint64_t lo = x.second << shift; + uint64_t hi = (x.first << shift) | (x.second >> (64 - shift)); + return std::make_pair(hi, lo); +} + +vixl_uint128_t Simulator::Eor128(vixl_uint128_t x, vixl_uint128_t y) const { + return std::make_pair(x.first ^ y.first, x.second ^ y.second); +} + +vixl_uint128_t Simulator::Neg128(vixl_uint128_t x) { + // Negate the integer value. Throw an assertion when the input is INT128_MIN. + VIXL_ASSERT((x.first != GetSignMask(64)) || (x.second != 0)); + x.first = ~x.first; + x.second = ~x.second; + return Add128(x, {0, 1}); +} + +vixl_uint128_t Simulator::Mul64(uint64_t x, uint64_t y) { + bool neg_result = false; + if ((x >> 63) == 1) { + x = UnsignedNegate(x); + neg_result = !neg_result; + } + if ((y >> 63) == 1) { + y = UnsignedNegate(y); + neg_result = !neg_result; + } + + uint64_t x_lo = x & 0xffffffff; + uint64_t x_hi = x >> 32; + uint64_t y_lo = y & 0xffffffff; + uint64_t y_hi = y >> 32; + + uint64_t t1 = x_lo * y_hi; + uint64_t t2 = x_hi * y_lo; + vixl_uint128_t a = std::make_pair(0, x_lo * y_lo); + vixl_uint128_t b = std::make_pair(t1 >> 32, t1 << 32); + vixl_uint128_t c = std::make_pair(t2 >> 32, t2 << 32); + vixl_uint128_t d = std::make_pair(x_hi * y_hi, 0); + + vixl_uint128_t result = Add128(a, b); + result = Add128(result, c); + result = Add128(result, d); + return neg_result ? std::make_pair(UnsignedNegate(result.first) - 1, + UnsignedNegate(result.second)) + : result; +} + +vixl_uint128_t Simulator::PolynomialMult128(uint64_t op1, + uint64_t op2, + int lane_size_in_bits) const { + VIXL_ASSERT(static_cast(lane_size_in_bits) <= kDRegSize); + vixl_uint128_t result = std::make_pair(0, 0); + vixl_uint128_t op2q = std::make_pair(0, op2); + for (int i = 0; i < lane_size_in_bits; i++) { + if ((op1 >> i) & 1) { + result = Eor128(result, Lsl128(op2q, i)); + } + } + return result; +} + +int64_t Simulator::ShiftOperand(unsigned reg_size, + uint64_t uvalue, + Shift shift_type, + unsigned amount) const { + VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) || + (reg_size == kSRegSize) || (reg_size == kDRegSize)); + if (amount > 0) { + uint64_t mask = GetUintMask(reg_size); + bool is_negative = (uvalue & GetSignMask(reg_size)) != 0; + // The behavior is undefined in c++ if the shift amount greater than or + // equal to the register lane size. Work out the shifted result based on + // architectural behavior before performing the c++ type shift operations. + switch (shift_type) { + case LSL: + if (amount >= reg_size) { + return UINT64_C(0); + } + uvalue <<= amount; + break; + case LSR: + if (amount >= reg_size) { + return UINT64_C(0); + } + uvalue >>= amount; + break; + case ASR: + if (amount >= reg_size) { + return is_negative ? ~UINT64_C(0) : UINT64_C(0); + } + uvalue >>= amount; + if (is_negative) { + // Simulate sign-extension to 64 bits. + uvalue |= ~UINT64_C(0) << (reg_size - amount); + } + break; + case ROR: { + uvalue = RotateRight(uvalue, amount, reg_size); + break; + } + default: + VIXL_UNIMPLEMENTED(); + return 0; + } + uvalue &= mask; + } + + int64_t result; + memcpy(&result, &uvalue, sizeof(result)); + return result; +} + + +int64_t Simulator::ExtendValue(unsigned reg_size, + int64_t value, + Extend extend_type, + unsigned left_shift) const { + switch (extend_type) { + case UXTB: + value &= kByteMask; + break; + case UXTH: + value &= kHalfWordMask; + break; + case UXTW: + value &= kWordMask; + break; + case SXTB: + value &= kByteMask; + if ((value & 0x80) != 0) { + value |= ~UINT64_C(0) << 8; + } + break; + case SXTH: + value &= kHalfWordMask; + if ((value & 0x8000) != 0) { + value |= ~UINT64_C(0) << 16; + } + break; + case SXTW: + value &= kWordMask; + if ((value & 0x80000000) != 0) { + value |= ~UINT64_C(0) << 32; + } + break; + case UXTX: + case SXTX: + break; + default: + VIXL_UNREACHABLE(); + } + return ShiftOperand(reg_size, value, LSL, left_shift); +} + + +void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) { + AssertSupportedFPCR(); + + // TODO: This assumes that the C++ implementation handles comparisons in the + // way that we expect (as per AssertSupportedFPCR()). + bool process_exception = false; + if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) { + ReadNzcv().SetRawValue(FPUnorderedFlag); + if (IsSignallingNaN(val0) || IsSignallingNaN(val1) || + (trap == EnableTrap)) { + process_exception = true; + } + } else if (val0 < val1) { + ReadNzcv().SetRawValue(FPLessThanFlag); + } else if (val0 > val1) { + ReadNzcv().SetRawValue(FPGreaterThanFlag); + } else if (val0 == val1) { + ReadNzcv().SetRawValue(FPEqualFlag); + } else { + VIXL_UNREACHABLE(); + } + LogSystemRegister(NZCV); + if (process_exception) FPProcessException(); +} + + +uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const { + VIXL_ASSERT(mem_op.IsValid()); + int64_t base = ReadRegister(mem_op.GetBaseRegister()); + if (mem_op.IsImmediateOffset()) { + return base + mem_op.GetOffset(); + } else { + VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid()); + int64_t offset = ReadRegister(mem_op.GetRegisterOffset()); + unsigned shift_amount = mem_op.GetShiftAmount(); + if (mem_op.GetShift() != NO_SHIFT) { + offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount); + } + if (mem_op.GetExtend() != NO_EXTEND) { + offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount); + } + return static_cast(base + offset); + } +} + + +Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize( + unsigned reg_size, unsigned lane_size) { + VIXL_ASSERT(reg_size >= lane_size); + + uint32_t format = 0; + if (reg_size != lane_size) { + switch (reg_size) { + default: + VIXL_UNREACHABLE(); + break; + case kQRegSizeInBytes: + format = kPrintRegAsQVector; + break; + case kDRegSizeInBytes: + format = kPrintRegAsDVector; + break; + } + } + + switch (lane_size) { + default: + VIXL_UNREACHABLE(); + break; + case kQRegSizeInBytes: + format |= kPrintReg1Q; + break; + case kDRegSizeInBytes: + format |= kPrintReg1D; + break; + case kSRegSizeInBytes: + format |= kPrintReg1S; + break; + case kHRegSizeInBytes: + format |= kPrintReg1H; + break; + case kBRegSizeInBytes: + format |= kPrintReg1B; + break; + } + // These sizes would be duplicate case labels. + VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes); + VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes); + VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D); + VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S); + + return static_cast(format); +} + + +Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat( + VectorFormat vform) { + switch (vform) { + default: + VIXL_UNREACHABLE(); + return kPrintReg16B; + case kFormat16B: + return kPrintReg16B; + case kFormat8B: + return kPrintReg8B; + case kFormat8H: + return kPrintReg8H; + case kFormat4H: + return kPrintReg4H; + case kFormat4S: + return kPrintReg4S; + case kFormat2S: + return kPrintReg2S; + case kFormat2D: + return kPrintReg2D; + case kFormat1D: + return kPrintReg1D; + + case kFormatB: + return kPrintReg1B; + case kFormatH: + return kPrintReg1H; + case kFormatS: + return kPrintReg1S; + case kFormatD: + return kPrintReg1D; + + case kFormatVnB: + return kPrintRegVnB; + case kFormatVnH: + return kPrintRegVnH; + case kFormatVnS: + return kPrintRegVnS; + case kFormatVnD: + return kPrintRegVnD; + } +} + + +Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP( + VectorFormat vform) { + switch (vform) { + default: + VIXL_UNREACHABLE(); + return kPrintReg16B; + case kFormat8H: + return kPrintReg8HFP; + case kFormat4H: + return kPrintReg4HFP; + case kFormat4S: + return kPrintReg4SFP; + case kFormat2S: + return kPrintReg2SFP; + case kFormat2D: + return kPrintReg2DFP; + case kFormat1D: + return kPrintReg1DFP; + case kFormatH: + return kPrintReg1HFP; + case kFormatS: + return kPrintReg1SFP; + case kFormatD: + return kPrintReg1DFP; + } +} + +void Simulator::PrintRegisters() { + for (unsigned i = 0; i < kNumberOfRegisters; i++) { + if (i == kSpRegCode) i = kSPRegInternalCode; + PrintRegister(i); + } +} + +void Simulator::PrintVRegisters() { + for (unsigned i = 0; i < kNumberOfVRegisters; i++) { + PrintVRegister(i); + } +} + +void Simulator::PrintZRegisters() { + for (unsigned i = 0; i < kNumberOfZRegisters; i++) { + PrintZRegister(i); + } +} + +void Simulator::PrintWrittenRegisters() { + for (unsigned i = 0; i < kNumberOfRegisters; i++) { + if (registers_[i].WrittenSinceLastLog()) { + if (i == kSpRegCode) i = kSPRegInternalCode; + PrintRegister(i); + } + } +} + +void Simulator::PrintWrittenVRegisters() { + bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE); + for (unsigned i = 0; i < kNumberOfVRegisters; i++) { + if (vregisters_[i].WrittenSinceLastLog()) { + // Z registers are initialised in the constructor before the user can + // configure the CPU features, so we must also check for SVE here. + if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) { + PrintZRegister(i); + } else { + PrintVRegister(i); + } + } + } +} + +void Simulator::PrintWrittenPRegisters() { + // P registers are initialised in the constructor before the user can + // configure the CPU features, so we must check for SVE here. + if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return; + for (unsigned i = 0; i < kNumberOfPRegisters; i++) { + if (pregisters_[i].WrittenSinceLastLog()) { + PrintPRegister(i); + } + } + if (ReadFFR().WrittenSinceLastLog()) PrintFFR(); +} + +void Simulator::PrintSystemRegisters() { + PrintSystemRegister(NZCV); + PrintSystemRegister(FPCR); +} + +void Simulator::PrintRegisterValue(const uint8_t* value, + int value_size, + PrintRegisterFormat format) { + int print_width = GetPrintRegSizeInBytes(format); + VIXL_ASSERT(print_width <= value_size); + for (int i = value_size - 1; i >= print_width; i--) { + // Pad with spaces so that values align vertically. + fprintf(stream_, " "); + // If we aren't explicitly printing a partial value, ensure that the + // unprinted bits are zero. + VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0)); + } + fprintf(stream_, "0x"); + for (int i = print_width - 1; i >= 0; i--) { + fprintf(stream_, "%02x", value[i]); + } +} + +void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value, + uint16_t lane_mask, + PrintRegisterFormat format) { + VIXL_ASSERT((format & kPrintRegAsFP) != 0); + int lane_size = GetPrintRegLaneSizeInBytes(format); + fprintf(stream_, " ("); + bool last_inactive = false; + const char* sep = ""; + for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") { + bool access = (lane_mask & (1 << (i * lane_size))) != 0; + if (access) { + // Read the lane as a double, so we can format all FP types in the same + // way. We squash NaNs, and a double can exactly represent any other value + // that the smaller types can represent, so this is lossless. + double element; + switch (lane_size) { + case kHRegSizeInBytes: { + Float16 element_fp16; + VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes); + memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16)); + element = FPToDouble(element_fp16, kUseDefaultNaN); + break; + } + case kSRegSizeInBytes: { + float element_fp32; + memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32)); + element = static_cast(element_fp32); + break; + } + case kDRegSizeInBytes: { + memcpy(&element, &value[i * lane_size], sizeof(element)); + break; + } + default: + VIXL_UNREACHABLE(); + fprintf(stream_, "{UnknownFPValue}"); + continue; + } + if (IsNaN(element)) { + // The fprintf behaviour for NaNs is implementation-defined. Always + // print "nan", so that traces are consistent. + fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal); + } else { + fprintf(stream_, + "%s%s%#.4g%s", + sep, + clr_vreg_value, + element, + clr_normal); + } + last_inactive = false; + } else if (!last_inactive) { + // Replace each contiguous sequence of inactive lanes with "...". + fprintf(stream_, "%s...", sep); + last_inactive = true; + } + } + fprintf(stream_, ")"); +} + +void Simulator::PrintRegister(int code, + PrintRegisterFormat format, + const char* suffix) { + VIXL_ASSERT((static_cast(code) < kNumberOfRegisters) || + (static_cast(code) == kSPRegInternalCode)); + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar); + VIXL_ASSERT((format & kPrintRegAsFP) == 0); + + SimRegister* reg; + SimRegister zero; + if (code == kZeroRegCode) { + reg = &zero; + } else { + // registers_[31] holds the SP. + VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31); + reg = ®isters_[code % kNumberOfRegisters]; + } + + // We trace register writes as whole register values, implying that any + // unprinted bits are all zero: + // "# x{code}: 0x{-----value----}" + // "# w{code}: 0x{-value}" + // Stores trace partial register values, implying nothing about the unprinted + // bits: + // "# x{code}<63:0>: 0x{-----value----}" + // "# x{code}<31:0>: 0x{-value}" + // "# x{code}<15:0>: 0x{--}" + // "# x{code}<7:0>: 0x{}" + + bool is_partial = (format & kPrintRegPartial) != 0; + unsigned print_reg_size = GetPrintRegSizeInBits(format); + std::stringstream name; + if (is_partial) { + name << XRegNameForCode(code) << GetPartialRegSuffix(format); + } else { + // Notify the register that it has been logged, but only if we're printing + // all of it. + reg->NotifyRegisterLogged(); + switch (print_reg_size) { + case kWRegSize: + name << WRegNameForCode(code); + break; + case kXRegSize: + name << XRegNameForCode(code); + break; + default: + VIXL_UNREACHABLE(); + return; + } + } + + fprintf(stream_, + "# %s%*s: %s", + clr_reg_name, + kPrintRegisterNameFieldWidth, + name.str().c_str(), + clr_reg_value); + PrintRegisterValue(*reg, format); + fprintf(stream_, "%s%s", clr_normal, suffix); +} + +void Simulator::PrintVRegister(int code, + PrintRegisterFormat format, + const char* suffix) { + VIXL_ASSERT(static_cast(code) < kNumberOfVRegisters); + VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) || + ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) || + ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector)); + + // We trace register writes as whole register values, implying that any + // unprinted bits are all zero: + // "# v{code}: 0x{-------------value------------}" + // "# d{code}: 0x{-----value----}" + // "# s{code}: 0x{-value}" + // "# h{code}: 0x{--}" + // "# b{code}: 0x{}" + // Stores trace partial register values, implying nothing about the unprinted + // bits: + // "# v{code}<127:0>: 0x{-------------value------------}" + // "# v{code}<63:0>: 0x{-----value----}" + // "# v{code}<31:0>: 0x{-value}" + // "# v{code}<15:0>: 0x{--}" + // "# v{code}<7:0>: 0x{}" + + bool is_partial = ((format & kPrintRegPartial) != 0); + std::stringstream name; + unsigned print_reg_size = GetPrintRegSizeInBits(format); + if (is_partial) { + name << VRegNameForCode(code) << GetPartialRegSuffix(format); + } else { + // Notify the register that it has been logged, but only if we're printing + // all of it. + vregisters_[code].NotifyRegisterLogged(); + switch (print_reg_size) { + case kBRegSize: + name << BRegNameForCode(code); + break; + case kHRegSize: + name << HRegNameForCode(code); + break; + case kSRegSize: + name << SRegNameForCode(code); + break; + case kDRegSize: + name << DRegNameForCode(code); + break; + case kQRegSize: + name << VRegNameForCode(code); + break; + default: + VIXL_UNREACHABLE(); + return; + } + } + + fprintf(stream_, + "# %s%*s: %s", + clr_vreg_name, + kPrintRegisterNameFieldWidth, + name.str().c_str(), + clr_vreg_value); + PrintRegisterValue(vregisters_[code], format); + fprintf(stream_, "%s", clr_normal); + if ((format & kPrintRegAsFP) != 0) { + PrintRegisterValueFPAnnotations(vregisters_[code], format); + } + fprintf(stream_, "%s", suffix); +} + +void Simulator::PrintVRegistersForStructuredAccess(int rt_code, + int reg_count, + uint16_t focus_mask, + PrintRegisterFormat format) { + bool print_fp = (format & kPrintRegAsFP) != 0; + // Suppress FP formatting, so we can specify the lanes we're interested in. + PrintRegisterFormat format_no_fp = + static_cast(format & ~kPrintRegAsFP); + + for (int r = 0; r < reg_count; r++) { + int code = (rt_code + r) % kNumberOfVRegisters; + PrintVRegister(code, format_no_fp, ""); + if (print_fp) { + PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format); + } + fprintf(stream_, "\n"); + } +} + +void Simulator::PrintZRegistersForStructuredAccess(int rt_code, + int q_index, + int reg_count, + uint16_t focus_mask, + PrintRegisterFormat format) { + bool print_fp = (format & kPrintRegAsFP) != 0; + // Suppress FP formatting, so we can specify the lanes we're interested in. + PrintRegisterFormat format_no_fp = + static_cast(format & ~kPrintRegAsFP); + + PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format); + + const unsigned size = kQRegSizeInBytes; + unsigned byte_index = q_index * size; + const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index; + VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes()); + + for (int r = 0; r < reg_count; r++) { + int code = (rt_code + r) % kNumberOfZRegisters; + PrintPartialZRegister(code, q_index, format_no_fp, ""); + if (print_fp) { + PrintRegisterValueFPAnnotations(value, focus_mask, format_q); + } + fprintf(stream_, "\n"); + } +} + +void Simulator::PrintZRegister(int code, PrintRegisterFormat format) { + // We're going to print the register in parts, so force a partial format. + format = GetPrintRegPartial(format); + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector); + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + for (unsigned i = 0; i < (vl / kQRegSize); i++) { + PrintPartialZRegister(code, i, format); + } + vregisters_[code].NotifyRegisterLogged(); +} + +void Simulator::PrintPRegister(int code, PrintRegisterFormat format) { + // We're going to print the register in parts, so force a partial format. + format = GetPrintRegPartial(format); + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector); + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + for (unsigned i = 0; i < (vl / kQRegSize); i++) { + PrintPartialPRegister(code, i, format); + } + pregisters_[code].NotifyRegisterLogged(); +} + +void Simulator::PrintFFR(PrintRegisterFormat format) { + // We're going to print the register in parts, so force a partial format. + format = GetPrintRegPartial(format); + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector); + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + SimPRegister& ffr = ReadFFR(); + for (unsigned i = 0; i < (vl / kQRegSize); i++) { + PrintPartialPRegister("FFR", ffr, i, format); + } + ffr.NotifyRegisterLogged(); +} + +void Simulator::PrintPartialZRegister(int code, + int q_index, + PrintRegisterFormat format, + const char* suffix) { + VIXL_ASSERT(static_cast(code) < kNumberOfZRegisters); + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector); + VIXL_ASSERT((format & kPrintRegPartial) != 0); + VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits()); + + // We _only_ trace partial Z register values in Q-sized chunks, because + // they're often too large to reasonably fit on a single line. Each line + // implies nothing about the unprinted bits. + // "# z{code}<127:0>: 0x{-------------value------------}" + + format = GetPrintRegAsQChunkOfSVE(format); + + const unsigned size = kQRegSizeInBytes; + unsigned byte_index = q_index * size; + const uint8_t* value = vregisters_[code].GetBytes() + byte_index; + VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes()); + + int lsb = q_index * kQRegSize; + int msb = lsb + kQRegSize - 1; + std::stringstream name; + name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>'; + + fprintf(stream_, + "# %s%*s: %s", + clr_vreg_name, + kPrintRegisterNameFieldWidth, + name.str().c_str(), + clr_vreg_value); + PrintRegisterValue(value, size, format); + fprintf(stream_, "%s", clr_normal); + if ((format & kPrintRegAsFP) != 0) { + PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format); + } + fprintf(stream_, "%s", suffix); +} + +void Simulator::PrintPartialPRegister(const char* name, + const SimPRegister& reg, + int q_index, + PrintRegisterFormat format, + const char* suffix) { + VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector); + VIXL_ASSERT((format & kPrintRegPartial) != 0); + VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits()); + + // We don't currently use the format for anything here. + USE(format); + + // We _only_ trace partial P register values, because they're often too large + // to reasonably fit on a single line. Each line implies nothing about the + // unprinted bits. + // + // We print values in binary, with spaces between each bit, in order for the + // bits to align with the Z register bytes that they predicate. + // "# {name}<15:0>: 0b{-------------value------------}" + + int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit; + int lsb = q_index * print_size_in_bits; + int msb = lsb + print_size_in_bits - 1; + std::stringstream prefix; + prefix << name << '<' << msb << ':' << lsb << '>'; + + fprintf(stream_, + "# %s%*s: %s0b", + clr_preg_name, + kPrintRegisterNameFieldWidth, + prefix.str().c_str(), + clr_preg_value); + for (int i = msb; i >= lsb; i--) { + fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0'); + } + fprintf(stream_, "%s%s", clr_normal, suffix); +} + +void Simulator::PrintPartialPRegister(int code, + int q_index, + PrintRegisterFormat format, + const char* suffix) { + VIXL_ASSERT(static_cast(code) < kNumberOfPRegisters); + PrintPartialPRegister(PRegNameForCode(code), + pregisters_[code], + q_index, + format, + suffix); +} + +void Simulator::PrintSystemRegister(SystemRegister id) { + switch (id) { + case NZCV: + fprintf(stream_, + "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", + clr_flag_name, + clr_flag_value, + ReadNzcv().GetN(), + ReadNzcv().GetZ(), + ReadNzcv().GetC(), + ReadNzcv().GetV(), + clr_normal); + break; + case FPCR: { + static const char* rmode[] = {"0b00 (Round to Nearest)", + "0b01 (Round towards Plus Infinity)", + "0b10 (Round towards Minus Infinity)", + "0b11 (Round towards Zero)"}; + VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode)); + fprintf(stream_, + "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", + clr_flag_name, + clr_flag_value, + ReadFpcr().GetAHP(), + ReadFpcr().GetDN(), + ReadFpcr().GetFZ(), + rmode[ReadFpcr().GetRMode()], + clr_normal); + break; + } + default: + VIXL_UNREACHABLE(); + } +} + +void Simulator::PrintGCS(bool is_push, uint64_t addr, size_t entry) { + const char* arrow = is_push ? "<-" : "->"; + fprintf(stream_, + "# %sgcs0x%04" PRIu64 "[%zx]: %s %s 0x%016" PRIx64 "\n", + clr_flag_name, + GCSManager::GetGCSIndexFromToken(GetGCSToken()), + entry, + clr_normal, + arrow, + addr); +} + +uint16_t Simulator::PrintPartialAccess(uint16_t access_mask, + uint16_t future_access_mask, + int struct_element_count, + int lane_size_in_bytes, + const char* op, + uintptr_t address, + int reg_size_in_bytes) { + // We want to assume that we'll access at least one lane. + VIXL_ASSERT(access_mask != 0); + VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) || + (reg_size_in_bytes == kQRegSizeInBytes)); + bool started_annotation = false; + // Indent to match the register field, the fixed formatting, and the value + // prefix ("0x"): "# {name}: 0x" + fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, ""); + // First, annotate the lanes (byte by byte). + for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) { + bool access = (access_mask & (1 << lane)) != 0; + bool future = (future_access_mask & (1 << lane)) != 0; + if (started_annotation) { + // If we've started an annotation, draw a horizontal line in addition to + // any other symbols. + if (access) { + fprintf(stream_, "─╨"); + } else if (future) { + fprintf(stream_, "─║"); + } else { + fprintf(stream_, "──"); + } + } else { + if (access) { + started_annotation = true; + fprintf(stream_, " â•™"); + } else if (future) { + fprintf(stream_, " â•‘"); + } else { + fprintf(stream_, " "); + } + } + } + VIXL_ASSERT(started_annotation); + fprintf(stream_, "─ 0x"); + int lane_size_in_nibbles = lane_size_in_bytes * 2; + // Print the most-significant struct element first. + const char* sep = ""; + for (int i = struct_element_count - 1; i >= 0; i--) { + int offset = lane_size_in_bytes * i; + auto nibble = MemReadUint(lane_size_in_bytes, address + offset); + VIXL_ASSERT(nibble); + fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, *nibble); + sep = "'"; + } + fprintf(stream_, + " %s %s0x%016" PRIxPTR "%s\n", + op, + clr_memory_address, + address, + clr_normal); + return future_access_mask & ~access_mask; +} + +void Simulator::PrintAccess(int code, + PrintRegisterFormat format, + const char* op, + uintptr_t address) { + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + if ((format & kPrintRegPartial) == 0) { + if (code != kZeroRegCode) { + registers_[code].NotifyRegisterLogged(); + } + } + // Scalar-format accesses use a simple format: + // "# {reg}: 0x{value} -> {address}" + + // Suppress the newline, so the access annotation goes on the same line. + PrintRegister(code, format, ""); + fprintf(stream_, + " %s %s0x%016" PRIxPTR "%s\n", + op, + clr_memory_address, + address, + clr_normal); +} + +void Simulator::PrintVAccess(int code, + PrintRegisterFormat format, + const char* op, + uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // Scalar-format accesses use a simple format: + // "# v{code}: 0x{value} -> {address}" + + // Suppress the newline, so the access annotation goes on the same line. + PrintVRegister(code, format, ""); + fprintf(stream_, + " %s %s0x%016" PRIxPTR "%s\n", + op, + clr_memory_address, + address, + clr_normal); +} + +void Simulator::PrintVStructAccess(int rt_code, + int reg_count, + PrintRegisterFormat format, + const char* op, + uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // For example: + // "# v{code}: 0x{value}" + // "# ...: 0x{value}" + // "# â•‘ ╙─ {struct_value} -> {lowest_address}" + // "# ╙───── {struct_value} -> {highest_address}" + + uint16_t lane_mask = GetPrintRegLaneMask(format); + PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format); + + int reg_size_in_bytes = GetPrintRegSizeInBytes(format); + int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format); + for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) { + uint16_t access_mask = 1 << i; + VIXL_ASSERT((lane_mask & access_mask) != 0); + lane_mask = PrintPartialAccess(access_mask, + lane_mask, + reg_count, + lane_size_in_bytes, + op, + address + (i * reg_count)); + } +} + +void Simulator::PrintVSingleStructAccess(int rt_code, + int reg_count, + int lane, + PrintRegisterFormat format, + const char* op, + uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // For example: + // "# v{code}: 0x{value}" + // "# ...: 0x{value}" + // "# ╙───── {struct_value} -> {address}" + + int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format); + uint16_t lane_mask = 1 << (lane * lane_size_in_bytes); + PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format); + PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address); +} + +void Simulator::PrintVReplicatingStructAccess(int rt_code, + int reg_count, + PrintRegisterFormat format, + const char* op, + uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // For example: + // "# v{code}: 0x{value}" + // "# ...: 0x{value}" + // "# ╙─╨─╨─╨─ {struct_value} -> {address}" + + int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format); + uint16_t lane_mask = GetPrintRegLaneMask(format); + PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format); + PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address); +} + +void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // Scalar-format accesses are split into separate chunks, each of which uses a + // simple format: + // "# z{code}<127:0>: 0x{value} -> {address}" + // "# z{code}<255:128>: 0x{value} -> {address + 16}" + // "# z{code}<383:256>: 0x{value} -> {address + 32}" + // etc + + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) { + // Suppress the newline, so the access annotation goes on the same line. + PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, ""); + fprintf(stream_, + " %s %s0x%016" PRIxPTR "%s\n", + op, + clr_memory_address, + address, + clr_normal); + address += kQRegSizeInBytes; + } +} + +void Simulator::PrintZStructAccess(int rt_code, + int reg_count, + const LogicPRegister& pg, + PrintRegisterFormat format, + int msize_in_bytes, + const char* op, + const LogicSVEAddressVector& addr) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // For example: + // "# z{code}<255:128>: 0x{value}" + // "# ...<255:128>: 0x{value}" + // "# â•‘ ╙─ {struct_value} -> {first_address}" + // "# ╙───── {struct_value} -> {last_address}" + + // We're going to print the register in parts, so force a partial format. + bool skip_inactive_chunks = (format & kPrintRegPartial) != 0; + format = GetPrintRegPartial(format); + + int esize_in_bytes = GetPrintRegLaneSizeInBytes(format); + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + int lanes_per_q = kQRegSizeInBytes / esize_in_bytes; + for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) { + uint16_t pred = + pg.GetActiveMask(q_index) & GetPrintRegLaneMask(format); + if ((pred == 0) && skip_inactive_chunks) continue; + + PrintZRegistersForStructuredAccess(rt_code, + q_index, + reg_count, + pred, + format); + if (pred == 0) { + // This register chunk has no active lanes. The loop below would print + // nothing, so leave a blank line to keep structures grouped together. + fprintf(stream_, "#\n"); + continue; + } + for (int i = 0; i < lanes_per_q; i++) { + uint16_t access = 1 << (i * esize_in_bytes); + int lane = (q_index * lanes_per_q) + i; + // Skip inactive lanes. + if ((pred & access) == 0) continue; + pred = PrintPartialAccess(access, + pred, + reg_count, + msize_in_bytes, + op, + addr.GetStructAddress(lane)); + } + } + + // We print the whole register, even for stores. + for (int i = 0; i < reg_count; i++) { + vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged(); + } +} + +void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) { + VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0)); + + // Scalar-format accesses are split into separate chunks, each of which uses a + // simple format: + // "# p{code}<15:0>: 0b{value} -> {address}" + // "# p{code}<31:16>: 0b{value} -> {address + 2}" + // "# p{code}<47:32>: 0b{value} -> {address + 4}" + // etc + + int vl = GetVectorLengthInBits(); + VIXL_ASSERT((vl % kQRegSize) == 0); + for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) { + // Suppress the newline, so the access annotation goes on the same line. + PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, ""); + fprintf(stream_, + " %s %s0x%016" PRIxPTR "%s\n", + op, + clr_memory_address, + address, + clr_normal); + address += kQRegSizeInBytes; + } +} + +void Simulator::PrintMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) { + fprintf(stream_, + "# %s: %s0x%016" PRIxPTR " %s<- %s0x%02x%s", + clr_reg_name, + clr_memory_address, + dst, + clr_normal, + clr_reg_value, + value, + clr_normal); + + fprintf(stream_, + " <- %s0x%016" PRIxPTR "%s\n", + clr_memory_address, + src, + clr_normal); +} + +void Simulator::PrintRead(int rt_code, + PrintRegisterFormat format, + uintptr_t address) { + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + if (rt_code != kZeroRegCode) { + registers_[rt_code].NotifyRegisterLogged(); + } + PrintAccess(rt_code, format, "<-", address); +} + +void Simulator::PrintExtendingRead(int rt_code, + PrintRegisterFormat format, + int access_size_in_bytes, + uintptr_t address) { + int reg_size_in_bytes = GetPrintRegSizeInBytes(format); + if (access_size_in_bytes == reg_size_in_bytes) { + // There is no extension here, so print a simple load. + PrintRead(rt_code, format, address); + return; + } + VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes); + + // For sign- and zero-extension, make it clear that the resulting register + // value is different from what is loaded from memory. + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + if (rt_code != kZeroRegCode) { + registers_[rt_code].NotifyRegisterLogged(); + } + PrintRegister(rt_code, format); + PrintPartialAccess(1, + 0, + 1, + access_size_in_bytes, + "<-", + address, + kXRegSizeInBytes); +} + +void Simulator::PrintVRead(int rt_code, + PrintRegisterFormat format, + uintptr_t address) { + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + vregisters_[rt_code].NotifyRegisterLogged(); + PrintVAccess(rt_code, format, "<-", address); +} + +void Simulator::PrintWrite(int rt_code, + PrintRegisterFormat format, + uintptr_t address) { + // Because this trace doesn't represent a change to the source register's + // value, only print the relevant part of the value. + format = GetPrintRegPartial(format); + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + if (rt_code != kZeroRegCode) { + registers_[rt_code].NotifyRegisterLogged(); + } + PrintAccess(rt_code, format, "->", address); +} + +void Simulator::PrintVWrite(int rt_code, + PrintRegisterFormat format, + uintptr_t address) { + // Because this trace doesn't represent a change to the source register's + // value, only print the relevant part of the value. + format = GetPrintRegPartial(format); + // It only makes sense to write scalar values here. Vectors are handled by + // PrintVStructAccess. + VIXL_ASSERT(GetPrintRegLaneCount(format) == 1); + PrintVAccess(rt_code, format, "->", address); +} + +void Simulator::PrintTakenBranch(const Instruction* target) { + fprintf(stream_, + "# %sBranch%s to 0x%016" PRIx64 ".\n", + clr_branch_marker, + clr_normal, + reinterpret_cast(target)); +} + +// Visitors--------------------------------------------------------------------- + + +void Simulator::Visit(Metadata* metadata, const Instruction* instr) { + VIXL_ASSERT(metadata->count("form") > 0); + // Check for unallocated encodings. + if (metadata->count("unallocated") > 0) { + VisitUnallocated(instr); + return; + } + + std::string form = (*metadata)["form"]; + form_hash_ = Hash(form.c_str()); + const FormToVisitorFnMap* fv = Simulator::GetFormToVisitorFnMap(); + FormToVisitorFnMap::const_iterator it = fv->find(form_hash_); + if (it == fv->end()) { + VisitUnimplemented(instr); + } else { + (it->second)(this, instr); + } +} + +void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "match_p_p_zz"_h: + match(vform, pd, zn, zm, /* negate_match = */ false); + break; + case "nmatch_p_p_zz"_h: + match(vform, pd, zn, zm, /* negate_match = */ true); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_zeroing(pd, pg, pd); + PredTest(vform, pg, pd); +} + +void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + uint64_t src1 = ReadXRegister(instr->GetRn()); + uint64_t src2 = ReadXRegister(instr->GetRm()); + + uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1); + absdiff >>= LaneSizeInBytesLog2FromFormat(vform); + + bool no_conflict = false; + switch (form_hash_) { + case "whilerw_p_rr"_h: + no_conflict = (absdiff == 0); + break; + case "whilewr_p_rr"_h: + no_conflict = (absdiff == 0) || (src2 <= src1); + break; + default: + VIXL_UNIMPLEMENTED(); + } + + LogicPRegister dst(pd); + for (int i = 0; i < LaneCountFromFormat(vform); i++) { + dst.SetActive(vform, + i, + no_conflict || (static_cast(i) < absdiff)); + } + + PredTest(vform, GetPTrue(), pd); +} + +void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) { + VIXL_ASSERT(form_hash_ == "ext_z_zi_con"_h); + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters); + + int index = instr->GetSVEExtractImmediate(); + int vl = GetVectorLengthInBytes(); + index = (index >= vl) ? 0 : index; + + ext(kFormatVnB, zd, zn, zn2, index); +} + +void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "histseg_z_zz"_h: + if (instr->GetSVEVectorFormat() == kFormatVnB) { + histogram(kFormatVnB, + zd, + GetPTrue(), + zn, + zm, + /* do_segmented = */ true); + } else { + VIXL_UNIMPLEMENTED(); + } + break; + case "pmul_z_zz"_h: + pmul(kFormatVnB, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEMulIndex(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + // The encoding for B and H-sized lanes are redefined to encode the most + // significant bit of index for H-sized lanes. B-sized lanes are not + // supported. + if (vform == kFormatVnB) vform = kFormatVnH; + + VIXL_ASSERT((form_hash_ == "mul_z_zzi_d"_h) || + (form_hash_ == "mul_z_zzi_h"_h) || + (form_hash_ == "mul_z_zzi_s"_h)); + + SimVRegister temp; + dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex()); + mul(vform, zd, zn, temp); +} + +void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + // The encoding for B and H-sized lanes are redefined to encode the most + // significant bit of index for H-sized lanes. B-sized lanes are not + // supported. + if (vform == kFormatVnB) vform = kFormatVnH; + + VIXL_ASSERT( + (form_hash_ == "mla_z_zzzi_d"_h) || (form_hash_ == "mla_z_zzzi_h"_h) || + (form_hash_ == "mla_z_zzzi_s"_h) || (form_hash_ == "mls_z_zzzi_d"_h) || + (form_hash_ == "mls_z_zzzi_h"_h) || (form_hash_ == "mls_z_zzzi_s"_h)); + + SimVRegister temp; + dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex()); + if (instr->ExtractBit(10) == 0) { + mla(vform, zda, zda, zn, temp); + } else { + mls(vform, zda, zda, zn, temp); + } +} + +void Simulator::SimulateSVESaturatingMulHighIndex(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + // The encoding for B and H-sized lanes are redefined to encode the most + // significant bit of index for H-sized lanes. B-sized lanes are not + // supported. + if (vform == kFormatVnB) { + vform = kFormatVnH; + } + + SimVRegister temp; + dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex()); + switch (form_hash_) { + case "sqdmulh_z_zzi_h"_h: + case "sqdmulh_z_zzi_s"_h: + case "sqdmulh_z_zzi_d"_h: + sqdmulh(vform, zd, zn, temp); + break; + case "sqrdmulh_z_zzi_h"_h: + case "sqrdmulh_z_zzi_s"_h: + case "sqrdmulh_z_zzi_d"_h: + sqrdmulh(vform, zd, zn, temp); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister temp, zm_idx, zn_b, zn_t; + // Instead of calling the indexed form of the instruction logic, we call the + // vector form, which can reuse existing function logic without modification. + // Select the specified elements based on the index input and than pack them + // to the corresponding position. + VectorFormat vform_half = VectorFormatHalfWidth(vform); + dup_elements_to_segments(vform_half, temp, instr->GetSVEMulLongZmAndIndex()); + pack_even_elements(vform_half, zm_idx, temp); + + pack_even_elements(vform_half, zn_b, zn); + pack_odd_elements(vform_half, zn_t, zn); + + switch (form_hash_) { + case "smullb_z_zzi_s"_h: + case "smullb_z_zzi_d"_h: + smull(vform, zd, zn_b, zm_idx); + break; + case "smullt_z_zzi_s"_h: + case "smullt_z_zzi_d"_h: + smull(vform, zd, zn_t, zm_idx); + break; + case "sqdmullb_z_zzi_d"_h: + sqdmull(vform, zd, zn_b, zm_idx); + break; + case "sqdmullt_z_zzi_d"_h: + sqdmull(vform, zd, zn_t, zm_idx); + break; + case "umullb_z_zzi_s"_h: + case "umullb_z_zzi_d"_h: + umull(vform, zd, zn_b, zm_idx); + break; + case "umullt_z_zzi_s"_h: + case "umullt_z_zzi_d"_h: + umull(vform, zd, zn_t, zm_idx); + break; + case "sqdmullb_z_zzi_s"_h: + sqdmull(vform, zd, zn_b, zm_idx); + break; + case "sqdmullt_z_zzi_s"_h: + sqdmull(vform, zd, zn_t, zm_idx); + break; + case "smlalb_z_zzzi_s"_h: + case "smlalb_z_zzzi_d"_h: + smlal(vform, zd, zn_b, zm_idx); + break; + case "smlalt_z_zzzi_s"_h: + case "smlalt_z_zzzi_d"_h: + smlal(vform, zd, zn_t, zm_idx); + break; + case "smlslb_z_zzzi_s"_h: + case "smlslb_z_zzzi_d"_h: + smlsl(vform, zd, zn_b, zm_idx); + break; + case "smlslt_z_zzzi_s"_h: + case "smlslt_z_zzzi_d"_h: + smlsl(vform, zd, zn_t, zm_idx); + break; + case "umlalb_z_zzzi_s"_h: + case "umlalb_z_zzzi_d"_h: + umlal(vform, zd, zn_b, zm_idx); + break; + case "umlalt_z_zzzi_s"_h: + case "umlalt_z_zzzi_d"_h: + umlal(vform, zd, zn_t, zm_idx); + break; + case "umlslb_z_zzzi_s"_h: + case "umlslb_z_zzzi_d"_h: + umlsl(vform, zd, zn_b, zm_idx); + break; + case "umlslt_z_zzzi_s"_h: + case "umlslt_z_zzzi_d"_h: + umlsl(vform, zd, zn_t, zm_idx); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result, zd_b, zero; + + zero.Clear(); + pack_even_elements(kFormatVnH, zd_b, zd); + + switch (form_hash_) { + case "fcvtnt_z_p_z_s2h"_h: + fcvt(kFormatVnH, kFormatVnS, result, pg, zn); + pack_even_elements(kFormatVnH, result, result); + zip1(kFormatVnH, result, zd_b, result); + break; + case "bfcvt_z_p_z_s2bf"_h: + bfcvtn(kFormatVnH, result, zn); + zip1(kFormatVnH, result, result, zero); + break; + case "bfcvtnt_z_p_z_s2bf"_h: + bfcvtn(kFormatVnH, result, zn); + zip1(kFormatVnH, result, zd_b, result); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(kFormatVnS, zd, pg, result); +} + +void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result, zero, zd_b; + + zero.Clear(); + pack_even_elements(kFormatVnS, zd_b, zd); + + switch (form_hash_) { + case "fcvtnt_z_p_z_d2s"_h: + fcvt(kFormatVnS, kFormatVnD, result, pg, zn); + pack_even_elements(kFormatVnS, result, result); + zip1(kFormatVnS, result, zd_b, result); + break; + case "fcvtx_z_p_z_d2s"_h: + fcvtxn(kFormatVnS, result, zn); + zip1(kFormatVnS, result, result, zero); + break; + case "fcvtxnt_z_p_z_d2s"_h: + fcvtxn(kFormatVnS, result, zn); + zip1(kFormatVnS, result, zd_b, result); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(kFormatVnD, zd, pg, result); +} + +void Simulator::SimulateSVEFPConvertLong(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "fcvtlt_z_p_z_h2s"_h: + ext(kFormatVnB, result, zn, zn, kHRegSizeInBytes); + fcvt(kFormatVnS, kFormatVnH, zd, pg, result); + break; + case "fcvtlt_z_p_z_s2d"_h: + ext(kFormatVnB, result, zn, zn, kSRegSizeInBytes); + fcvt(kFormatVnD, kFormatVnS, zd, pg, result); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + if (vform != kFormatVnS) { + VIXL_UNIMPLEMENTED(); + } + + switch (form_hash_) { + case "urecpe_z_p_z"_h: + urecpe(vform, result, zn); + break; + case "ursqrte_z_p_z"_h: + ursqrte(vform, result, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(vform, zd, pg, result); +} + +void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "flogb_z_p_z"_h: + vform = instr->GetSVEVectorFormat(17); + flogb(vform, result, zn); + break; + case "sqabs_z_p_z"_h: + abs(vform, result, zn).SignedSaturate(vform); + break; + case "sqneg_z_p_z"_h: + neg(vform, result, zn).SignedSaturate(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(vform, zd, pg, result); +} + +void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + VIXL_ASSERT(form_hash_ == "histcnt_z_p_zz"_h); + if ((vform == kFormatVnS) || (vform == kFormatVnD)) { + histogram(vform, result, pg, zn, zm); + mov_zeroing(vform, zd, pg, result); + } else { + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + bool do_bext = false; + + switch (form_hash_) { + case "bdep_z_zz"_h: + bdep(vform, zd, zn, zm); + break; + case "bext_z_zz"_h: + do_bext = true; + VIXL_FALLTHROUGH(); + case "bgrp_z_zz"_h: + bgrp(vform, zd, zn, zm, do_bext); + break; + case "eorbt_z_zz"_h: + rotate_elements_right(vform, result, zm, 1); + SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result); + mov_alternating(vform, zd, result, 0); + break; + case "eortb_z_zz"_h: + rotate_elements_right(vform, result, zm, -1); + SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result); + mov_alternating(vform, zd, result, 1); + break; + case "mul_z_zz"_h: + mul(vform, zd, zn, zm); + break; + case "smulh_z_zz"_h: + smulh(vform, zd, zn, zm); + break; + case "sqdmulh_z_zz"_h: + sqdmulh(vform, zd, zn, zm); + break; + case "sqrdmulh_z_zz"_h: + sqrdmulh(vform, zd, zn, zm); + break; + case "umulh_z_zz"_h: + umulh(vform, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister zm_b, zm_t; + VectorFormat vform_half = VectorFormatHalfWidth(vform); + pack_even_elements(vform_half, zm_b, zm); + pack_odd_elements(vform_half, zm_t, zm); + + switch (form_hash_) { + case "saddwb_z_zz"_h: + saddw(vform, zd, zn, zm_b); + break; + case "saddwt_z_zz"_h: + saddw(vform, zd, zn, zm_t); + break; + case "ssubwb_z_zz"_h: + ssubw(vform, zd, zn, zm_b); + break; + case "ssubwt_z_zz"_h: + ssubw(vform, zd, zn, zm_t); + break; + case "uaddwb_z_zz"_h: + uaddw(vform, zd, zn, zm_b); + break; + case "uaddwt_z_zz"_h: + uaddw(vform, zd, zn, zm_t); + break; + case "usubwb_z_zz"_h: + usubw(vform, zd, zn, zm_b); + break; + case "usubwt_z_zz"_h: + usubw(vform, zd, zn, zm_t); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + int lane_size = shift_and_lane_size.second; + VIXL_ASSERT((lane_size >= 0) && + (static_cast(lane_size) <= kDRegSizeInBytesLog2)); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int shift_dist = shift_and_lane_size.first; + + switch (form_hash_) { + case "sli_z_zzi"_h: + // Shift distance is computed differently for left shifts. Convert the + // result. + shift_dist = (8 << lane_size) - shift_dist; + sli(vform, zd, zn, shift_dist); + break; + case "sri_z_zzi"_h: + sri(vform, zd, zn, shift_dist); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVENarrow(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + int lane_size = shift_and_lane_size.second; + VIXL_ASSERT((lane_size >= static_cast(kBRegSizeInBytesLog2)) && + (lane_size <= static_cast(kSRegSizeInBytesLog2))); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int right_shift_dist = shift_and_lane_size.first; + bool top = false; + + switch (form_hash_) { + case "sqxtnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqxtnb_z_zz"_h: + sqxtn(vform, result, zn); + break; + case "sqxtunt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqxtunb_z_zz"_h: + sqxtun(vform, result, zn); + break; + case "uqxtnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "uqxtnb_z_zz"_h: + uqxtn(vform, result, zn); + break; + case "rshrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "rshrnb_z_zi"_h: + rshrn(vform, result, zn, right_shift_dist); + break; + case "shrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "shrnb_z_zi"_h: + shrn(vform, result, zn, right_shift_dist); + break; + case "sqrshrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqrshrnb_z_zi"_h: + sqrshrn(vform, result, zn, right_shift_dist); + break; + case "sqrshrunt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqrshrunb_z_zi"_h: + sqrshrun(vform, result, zn, right_shift_dist); + break; + case "sqshrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqshrnb_z_zi"_h: + sqshrn(vform, result, zn, right_shift_dist); + break; + case "sqshrunt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "sqshrunb_z_zi"_h: + sqshrun(vform, result, zn, right_shift_dist); + break; + case "uqrshrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "uqrshrnb_z_zi"_h: + uqrshrn(vform, result, zn, right_shift_dist); + break; + case "uqshrnt_z_zi"_h: + top = true; + VIXL_FALLTHROUGH(); + case "uqshrnb_z_zi"_h: + uqshrn(vform, result, zn, right_shift_dist); + break; + default: + VIXL_UNIMPLEMENTED(); + } + + if (top) { + // Keep even elements, replace odd elements with the results. + xtn(vform, zd, zd); + zip1(vform, zd, zd, result); + } else { + // Zero odd elements, replace even elements with the results. + SimVRegister zero; + zero.Clear(); + zip1(vform, zd, result, zero); + } +} + +void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister temp, zn_b, zm_b, zn_t, zm_t; + + // Construct temporary registers containing the even (bottom) and odd (top) + // elements. + VectorFormat vform_half = VectorFormatHalfWidth(vform); + pack_even_elements(vform_half, zn_b, zn); + pack_even_elements(vform_half, zm_b, zm); + pack_odd_elements(vform_half, zn_t, zn); + pack_odd_elements(vform_half, zm_t, zm); + + switch (form_hash_) { + case "sabdlb_z_zz"_h: + sabdl(vform, zd, zn_b, zm_b); + break; + case "sabdlt_z_zz"_h: + sabdl(vform, zd, zn_t, zm_t); + break; + case "saddlb_z_zz"_h: + saddl(vform, zd, zn_b, zm_b); + break; + case "saddlbt_z_zz"_h: + saddl(vform, zd, zn_b, zm_t); + break; + case "saddlt_z_zz"_h: + saddl(vform, zd, zn_t, zm_t); + break; + case "ssublb_z_zz"_h: + ssubl(vform, zd, zn_b, zm_b); + break; + case "ssublbt_z_zz"_h: + ssubl(vform, zd, zn_b, zm_t); + break; + case "ssublt_z_zz"_h: + ssubl(vform, zd, zn_t, zm_t); + break; + case "ssubltb_z_zz"_h: + ssubl(vform, zd, zn_t, zm_b); + break; + case "uabdlb_z_zz"_h: + uabdl(vform, zd, zn_b, zm_b); + break; + case "uabdlt_z_zz"_h: + uabdl(vform, zd, zn_t, zm_t); + break; + case "uaddlb_z_zz"_h: + uaddl(vform, zd, zn_b, zm_b); + break; + case "uaddlt_z_zz"_h: + uaddl(vform, zd, zn_t, zm_t); + break; + case "usublb_z_zz"_h: + usubl(vform, zd, zn_b, zm_b); + break; + case "usublt_z_zz"_h: + usubl(vform, zd, zn_t, zm_t); + break; + case "sabalb_z_zzz"_h: + sabal(vform, zd, zn_b, zm_b); + break; + case "sabalt_z_zzz"_h: + sabal(vform, zd, zn_t, zm_t); + break; + case "uabalb_z_zzz"_h: + uabal(vform, zd, zn_b, zm_b); + break; + case "uabalt_z_zzz"_h: + uabal(vform, zd, zn_t, zm_t); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEPmull128(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister zn_temp, zm_temp; + + if (form_hash_ == "pmullb_z_zz_q"_h) { + pack_even_elements(kFormatVnD, zn_temp, zn); + pack_even_elements(kFormatVnD, zm_temp, zm); + } else { + VIXL_ASSERT(form_hash_ == "pmullt_z_zz_q"_h); + pack_odd_elements(kFormatVnD, zn_temp, zn); + pack_odd_elements(kFormatVnD, zm_temp, zm); + } + pmull(kFormatVnQ, zd, zn_temp, zm_temp); +} + +void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister temp, zn_b, zm_b, zn_t, zm_t; + VectorFormat vform_half = VectorFormatHalfWidth(vform); + pack_even_elements(vform_half, zn_b, zn); + pack_even_elements(vform_half, zm_b, zm); + pack_odd_elements(vform_half, zn_t, zn); + pack_odd_elements(vform_half, zm_t, zm); + + switch (form_hash_) { + case "pmullb_z_zz"_h: + // Size '10' is undefined. + if (vform == kFormatVnS) { + VIXL_UNIMPLEMENTED(); + } + pmull(vform, zd, zn_b, zm_b); + break; + case "pmullt_z_zz"_h: + // Size '10' is undefined. + if (vform == kFormatVnS) { + VIXL_UNIMPLEMENTED(); + } + pmull(vform, zd, zn_t, zm_t); + break; + case "smullb_z_zz"_h: + smull(vform, zd, zn_b, zm_b); + break; + case "smullt_z_zz"_h: + smull(vform, zd, zn_t, zm_t); + break; + case "sqdmullb_z_zz"_h: + sqdmull(vform, zd, zn_b, zm_b); + break; + case "sqdmullt_z_zz"_h: + sqdmull(vform, zd, zn_t, zm_t); + break; + case "umullb_z_zz"_h: + umull(vform, zd, zn_b, zm_b); + break; + case "umullt_z_zz"_h: + umull(vform, zd, zn_t, zm_t); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + bool top = false; + + VectorFormat vform_src = instr->GetSVEVectorFormat(); + if (vform_src == kFormatVnB) { + VIXL_UNIMPLEMENTED(); + } + VectorFormat vform = VectorFormatHalfWidth(vform_src); + + switch (form_hash_) { + case "addhnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "addhnb_z_zz"_h: + addhn(vform, result, zn, zm); + break; + case "raddhnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "raddhnb_z_zz"_h: + raddhn(vform, result, zn, zm); + break; + case "rsubhnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "rsubhnb_z_zz"_h: + rsubhn(vform, result, zn, zm); + break; + case "subhnt_z_zz"_h: + top = true; + VIXL_FALLTHROUGH(); + case "subhnb_z_zz"_h: + subhn(vform, result, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + } + + if (top) { + // Keep even elements, replace odd elements with the results. + xtn(vform, zd, zd); + zip1(vform, zd, zd, result); + } else { + // Zero odd elements, replace even elements with the results. + SimVRegister zero; + zero.Clear(); + zip1(vform, zd, result, zero); + } +} + +void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister zn_b, zn_t; + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + int lane_size = shift_and_lane_size.second; + VIXL_ASSERT((lane_size >= 0) && + (static_cast(lane_size) <= kDRegSizeInBytesLog2)); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1); + int right_shift_dist = shift_and_lane_size.first; + int left_shift_dist = (8 << lane_size) - right_shift_dist; + + // Construct temporary registers containing the even (bottom) and odd (top) + // elements. + VectorFormat vform_half = VectorFormatHalfWidth(vform); + pack_even_elements(vform_half, zn_b, zn); + pack_odd_elements(vform_half, zn_t, zn); + + switch (form_hash_) { + case "sshllb_z_zi"_h: + sshll(vform, zd, zn_b, left_shift_dist); + break; + case "sshllt_z_zi"_h: + sshll(vform, zd, zn_t, left_shift_dist); + break; + case "ushllb_z_zi"_h: + ushll(vform, zd, zn_b, left_shift_dist); + break; + case "ushllt_z_zi"_h: + ushll(vform, zd, zn_t, left_shift_dist); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVESaturatingMulAddHigh(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + unsigned zm_code = instr->GetRm(); + int index = -1; + bool is_mla = false; + + switch (form_hash_) { + case "sqrdmlah_z_zzz"_h: + is_mla = true; + VIXL_FALLTHROUGH(); + case "sqrdmlsh_z_zzz"_h: + // Nothing to do. + break; + case "sqrdmlah_z_zzzi_h"_h: + is_mla = true; + VIXL_FALLTHROUGH(); + case "sqrdmlsh_z_zzzi_h"_h: + vform = kFormatVnH; + index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19); + zm_code = instr->ExtractBits(18, 16); + break; + case "sqrdmlah_z_zzzi_s"_h: + is_mla = true; + VIXL_FALLTHROUGH(); + case "sqrdmlsh_z_zzzi_s"_h: + vform = kFormatVnS; + index = instr->ExtractBits(20, 19); + zm_code = instr->ExtractBits(18, 16); + break; + case "sqrdmlah_z_zzzi_d"_h: + is_mla = true; + VIXL_FALLTHROUGH(); + case "sqrdmlsh_z_zzzi_d"_h: + vform = kFormatVnD; + index = instr->ExtractBit(20); + zm_code = instr->ExtractBits(19, 16); + break; + default: + VIXL_UNIMPLEMENTED(); + } + + SimVRegister& zm = ReadVRegister(zm_code); + SimVRegister zm_idx; + if (index >= 0) { + dup_elements_to_segments(vform, zm_idx, zm, index); + } + + if (is_mla) { + sqrdmlah(vform, zda, zn, (index >= 0) ? zm_idx : zm); + } else { + sqrdmlsh(vform, zda, zn, (index >= 0) ? zm_idx : zm); + } +} + +void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) { + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16)); + + SimVRegister temp, zm_idx, zn_b, zn_t; + Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11); + dup_elements_to_segments(kFormatVnS, temp, zm, index); + pack_even_elements(kFormatVnS, zm_idx, temp); + pack_even_elements(kFormatVnS, zn_b, zn); + pack_odd_elements(kFormatVnS, zn_t, zn); + + switch (form_hash_) { + case "sqdmlalb_z_zzzi_d"_h: + sqdmlal(kFormatVnD, zda, zn_b, zm_idx); + break; + case "sqdmlalt_z_zzzi_d"_h: + sqdmlal(kFormatVnD, zda, zn_t, zm_idx); + break; + case "sqdmlslb_z_zzzi_d"_h: + sqdmlsl(kFormatVnD, zda, zn_b, zm_idx); + break; + case "sqdmlslt_z_zzzi_d"_h: + sqdmlsl(kFormatVnD, zda, zn_t, zm_idx); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) { + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister temp, zn_b, zm_b, zn_t, zm_t; + pack_even_elements(kFormatVnH, zn_b, zn); + pack_even_elements(kFormatVnH, zm_b, zm); + pack_odd_elements(kFormatVnH, zn_t, zn); + pack_odd_elements(kFormatVnH, zm_t, zm); + + switch (form_hash_) { + case "fmlalb_z_zzz"_h: + fmlal(kFormatVnS, zda, zn_b, zm_b); + break; + case "fmlalt_z_zzz"_h: + fmlal(kFormatVnS, zda, zn_t, zm_t); + break; + case "fmlslb_z_zzz"_h: + fmlsl(kFormatVnS, zda, zn_b, zm_b); + break; + case "fmlslt_z_zzz"_h: + fmlsl(kFormatVnS, zda, zn_t, zm_t); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) { + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16)); + + SimVRegister temp, zm_idx, zn_b, zn_t; + Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11); + dup_elements_to_segments(kFormatVnH, temp, zm, index); + pack_even_elements(kFormatVnH, zm_idx, temp); + pack_even_elements(kFormatVnH, zn_b, zn); + pack_odd_elements(kFormatVnH, zn_t, zn); + + switch (form_hash_) { + case "fmlalb_z_zzzi_s"_h: + fmlal(kFormatVnS, zda, zn_b, zm_idx); + break; + case "fmlalt_z_zzzi_s"_h: + fmlal(kFormatVnS, zda, zn_t, zm_idx); + break; + case "fmlslb_z_zzzi_s"_h: + fmlsl(kFormatVnS, zda, zn_b, zm_idx); + break; + case "fmlslt_z_zzzi_s"_h: + fmlsl(kFormatVnS, zda, zn_t, zm_idx); + break; + case "sqdmlalb_z_zzzi_s"_h: + sqdmlal(kFormatVnS, zda, zn_b, zm_idx); + break; + case "sqdmlalt_z_zzzi_s"_h: + sqdmlal(kFormatVnS, zda, zn_t, zm_idx); + break; + case "sqdmlslb_z_zzzi_s"_h: + sqdmlsl(kFormatVnS, zda, zn_b, zm_idx); + break; + case "sqdmlslt_z_zzzi_s"_h: + sqdmlsl(kFormatVnS, zda, zn_t, zm_idx); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "sadalp_z_p_z"_h: + sadalp(vform, result, zn); + break; + case "uadalp_z_p_z"_h: + uadalp(vform, result, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(vform, zda, pg, result); +} + +void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) { + VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD; + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister not_zn; + not_(vform, not_zn, zn); + + switch (form_hash_) { + case "adclb_z_zzz"_h: + adcl(vform, zda, zn, zm, /* top = */ false); + break; + case "adclt_z_zzz"_h: + adcl(vform, zda, zn, zm, /* top = */ true); + break; + case "sbclb_z_zzz"_h: + adcl(vform, zda, not_zn, zm, /* top = */ false); + break; + case "sbclt_z_zzz"_h: + adcl(vform, zda, not_zn, zm, /* top = */ true); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "saba_z_zzz"_h: + saba(vform, zda, zn, zm); + break; + case "uaba_z_zzz"_h: + uaba(vform, zda, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) { + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + int rot = instr->ExtractBits(11, 10) * 90; + // vform and zm are only valid for the vector form of instruction. + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + // Inputs for indexed form of instruction. + SimVRegister& zm_h = ReadVRegister(instr->ExtractBits(18, 16)); + SimVRegister& zm_s = ReadVRegister(instr->ExtractBits(19, 16)); + int idx_h = instr->ExtractBits(20, 19); + int idx_s = instr->ExtractBit(20); + + switch (form_hash_) { + case "cmla_z_zzz"_h: + cmla(vform, zda, zda, zn, zm, rot); + break; + case "cmla_z_zzzi_h"_h: + cmla(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot); + break; + case "cmla_z_zzzi_s"_h: + cmla(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot); + break; + case "sqrdcmlah_z_zzz"_h: + sqrdcmlah(vform, zda, zda, zn, zm, rot); + break; + case "sqrdcmlah_z_zzzi_h"_h: + sqrdcmlah(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot); + break; + case "sqrdcmlah_z_zzzi_s"_h: + sqrdcmlah(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + int lane_size = shift_and_lane_size.second; + VIXL_ASSERT((lane_size >= 0) && + (static_cast(lane_size) <= kDRegSizeInBytesLog2)); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int shift_dist = shift_and_lane_size.first; + + switch (form_hash_) { + case "srsra_z_zi"_h: + srsra(vform, zd, zn, shift_dist); + break; + case "ssra_z_zi"_h: + ssra(vform, zd, zn, shift_dist); + break; + case "ursra_z_zi"_h: + ursra(vform, zd, zn, shift_dist); + break; + case "usra_z_zi"_h: + usra(vform, zd, zn, shift_dist); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister zero, zn_b, zm_b, zn_t, zm_t; + zero.Clear(); + + VectorFormat vform_half = VectorFormatHalfWidth(vform); + uzp1(vform_half, zn_b, zn, zero); + uzp1(vform_half, zm_b, zm, zero); + uzp2(vform_half, zn_t, zn, zero); + uzp2(vform_half, zm_t, zm, zero); + + switch (form_hash_) { + case "smlalb_z_zzz"_h: + smlal(vform, zda, zn_b, zm_b); + break; + case "smlalt_z_zzz"_h: + smlal(vform, zda, zn_t, zm_t); + break; + case "smlslb_z_zzz"_h: + smlsl(vform, zda, zn_b, zm_b); + break; + case "smlslt_z_zzz"_h: + smlsl(vform, zda, zn_t, zm_t); + break; + case "sqdmlalb_z_zzz"_h: + sqdmlal(vform, zda, zn_b, zm_b); + break; + case "sqdmlalbt_z_zzz"_h: + sqdmlal(vform, zda, zn_b, zm_t); + break; + case "sqdmlalt_z_zzz"_h: + sqdmlal(vform, zda, zn_t, zm_t); + break; + case "sqdmlslb_z_zzz"_h: + sqdmlsl(vform, zda, zn_b, zm_b); + break; + case "sqdmlslbt_z_zzz"_h: + sqdmlsl(vform, zda, zn_b, zm_t); + break; + case "sqdmlslt_z_zzz"_h: + sqdmlsl(vform, zda, zn_t, zm_t); + break; + case "umlalb_z_zzz"_h: + umlal(vform, zda, zn_b, zm_b); + break; + case "umlalt_z_zzz"_h: + umlal(vform, zda, zn_t, zm_t); + break; + case "umlslb_z_zzz"_h: + umlsl(vform, zda, zn_b, zm_b); + break; + case "umlslt_z_zzz"_h: + umlsl(vform, zda, zn_t, zm_t); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + int rot = instr->ExtractBits(11, 10) * 90; + unsigned zm_code = instr->GetRm(); + int index = -1; + + switch (form_hash_) { + case "cdot_z_zzz"_h: + // Nothing to do. + break; + case "cdot_z_zzzi_s"_h: + index = zm_code >> 3; + zm_code &= 0x7; + break; + case "cdot_z_zzzi_d"_h: + index = zm_code >> 4; + zm_code &= 0xf; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + SimVRegister temp; + SimVRegister& zm = ReadVRegister(zm_code); + if (index >= 0) dup_elements_to_segments(vform, temp, zm, index); + cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot); +} + +void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) { + VectorFormat vform = kFormatVnD; + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zk = ReadVRegister(instr->GetRn()); + SimVRegister temp; + + switch (form_hash_) { + case "bcax_z_zzz"_h: + bic(vform, temp, zm, zk); + eor(vform, zdn, temp, zdn); + break; + case "bsl1n_z_zzz"_h: + not_(vform, temp, zdn); + bsl(vform, zdn, zk, temp, zm); + break; + case "bsl2n_z_zzz"_h: + not_(vform, temp, zm); + bsl(vform, zdn, zk, zdn, temp); + break; + case "bsl_z_zzz"_h: + bsl(vform, zdn, zk, zdn, zm); + break; + case "eor3_z_zzz"_h: + eor(vform, temp, zdn, zm); + eor(vform, zdn, temp, zk); + break; + case "nbsl_z_zzz"_h: + bsl(vform, zdn, zk, zdn, zm); + not_(vform, zdn, zdn); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "shadd_z_p_zz"_h: + add(vform, result, zdn, zm).Halve(vform); + break; + case "shsub_z_p_zz"_h: + sub(vform, result, zdn, zm).Halve(vform); + break; + case "shsubr_z_p_zz"_h: + sub(vform, result, zm, zdn).Halve(vform); + break; + case "srhadd_z_p_zz"_h: + add(vform, result, zdn, zm).Halve(vform).Round(vform); + break; + case "uhadd_z_p_zz"_h: + add(vform, result, zdn, zm).Uhalve(vform); + break; + case "uhsub_z_p_zz"_h: + sub(vform, result, zdn, zm).Uhalve(vform); + break; + case "uhsubr_z_p_zz"_h: + sub(vform, result, zm, zdn).Uhalve(vform); + break; + case "urhadd_z_p_zz"_h: + add(vform, result, zdn, zm).Uhalve(vform).Round(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + switch (form_hash_) { + case "sqadd_z_p_zz"_h: + add(vform, result, zdn, zm).SignedSaturate(vform); + break; + case "sqsub_z_p_zz"_h: + sub(vform, result, zdn, zm).SignedSaturate(vform); + break; + case "sqsubr_z_p_zz"_h: + sub(vform, result, zm, zdn).SignedSaturate(vform); + break; + case "suqadd_z_p_zz"_h: + suqadd(vform, result, zdn, zm); + break; + case "uqadd_z_p_zz"_h: + add(vform, result, zdn, zm).UnsignedSaturate(vform); + break; + case "uqsub_z_p_zz"_h: + sub(vform, result, zdn, zm).UnsignedSaturate(vform); + break; + case "uqsubr_z_p_zz"_h: + sub(vform, result, zm, zdn).UnsignedSaturate(vform); + break; + case "usqadd_z_p_zz"_h: + usqadd(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::SimulateSVEIntArithPair(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "addp_z_p_zz"_h: + addp(vform, result, zdn, zm); + break; + case "smaxp_z_p_zz"_h: + smaxp(vform, result, zdn, zm); + break; + case "sminp_z_p_zz"_h: + sminp(vform, result, zdn, zm); + break; + case "umaxp_z_p_zz"_h: + umaxp(vform, result, zdn, zm); + break; + case "uminp_z_p_zz"_h: + uminp(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimVRegister result; + + switch (form_hash_) { + case "faddp_z_p_zz"_h: + faddp(vform, result, zdn, zm); + break; + case "fmaxnmp_z_p_zz"_h: + fmaxnmp(vform, result, zdn, zm); + break; + case "fmaxp_z_p_zz"_h: + fmaxp(vform, result, zdn, zm); + break; + case "fminnmp_z_p_zz"_h: + fminnmp(vform, result, zdn, zm); + break; + case "fminp_z_p_zz"_h: + fminp(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true); + unsigned lane_size = shift_and_lane_size.second; + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int right_shift_dist = shift_and_lane_size.first; + int left_shift_dist = (8 << lane_size) - right_shift_dist; + SimVRegister result; + + switch (form_hash_) { + case "sqshl_z_p_zi"_h: + sqshl(vform, result, zdn, left_shift_dist); + break; + case "sqshlu_z_p_zi"_h: + sqshlu(vform, result, zdn, left_shift_dist); + break; + case "srshr_z_p_zi"_h: + sshr(vform, result, zdn, right_shift_dist).Round(vform); + break; + case "uqshl_z_p_zi"_h: + uqshl(vform, result, zdn, left_shift_dist); + break; + case "urshr_z_p_zi"_h: + ushr(vform, result, zdn, right_shift_dist).Round(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) { + VIXL_ASSERT(form_hash_ == "xar_z_zzi"_h); + + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + unsigned lane_size = shift_and_lane_size.second; + VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int shift_dist = shift_and_lane_size.first; + eor(vform, zdn, zdn, zm); + ror(vform, zdn, zdn, shift_dist); +} + +void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + int rot = (instr->ExtractBit(10) == 0) ? 90 : 270; + + switch (form_hash_) { + case "cadd_z_zz"_h: + cadd(vform, zdn, zdn, zm, rot); + break; + case "sqcadd_z_zz"_h: + cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + uint64_t xm = ReadXRegister(instr->GetRm()); + + LogicSVEAddressVector addr(xm, &zn, kFormatVnD); + int msize = -1; + bool is_signed = false; + + switch (form_hash_) { + case "ldnt1b_z_p_ar_d_64_unscaled"_h: + msize = 0; + break; + case "ldnt1d_z_p_ar_d_64_unscaled"_h: + msize = 3; + break; + case "ldnt1h_z_p_ar_d_64_unscaled"_h: + msize = 1; + break; + case "ldnt1sb_z_p_ar_d_64_unscaled"_h: + msize = 0; + is_signed = true; + break; + case "ldnt1sh_z_p_ar_d_64_unscaled"_h: + msize = 1; + is_signed = true; + break; + case "ldnt1sw_z_p_ar_d_64_unscaled"_h: + msize = 2; + is_signed = true; + break; + case "ldnt1w_z_p_ar_d_64_unscaled"_h: + msize = 2; + break; + default: + VIXL_UNIMPLEMENTED(); + } + addr.SetMsizeInBytesLog2(msize); + SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed); +} + +void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + uint64_t xm = ReadXRegister(instr->GetRm()); + + LogicSVEAddressVector addr(xm, &zn, kFormatVnD); + VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_d_64_unscaled"_h) || + (form_hash_ == "stnt1d_z_p_ar_d_64_unscaled"_h) || + (form_hash_ == "stnt1h_z_p_ar_d_64_unscaled"_h) || + (form_hash_ == "stnt1w_z_p_ar_d_64_unscaled"_h)); + + addr.SetMsizeInBytesLog2( + instr->GetSVEMsizeFromDtype(/* is_signed = */ false)); + SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr); +} + +void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + uint64_t xm = ReadXRegister(instr->GetRm()); + + LogicSVEAddressVector addr(xm, &zn, kFormatVnS); + int msize = -1; + bool is_signed = false; + + switch (form_hash_) { + case "ldnt1b_z_p_ar_s_x32_unscaled"_h: + msize = 0; + break; + case "ldnt1h_z_p_ar_s_x32_unscaled"_h: + msize = 1; + break; + case "ldnt1sb_z_p_ar_s_x32_unscaled"_h: + msize = 0; + is_signed = true; + break; + case "ldnt1sh_z_p_ar_s_x32_unscaled"_h: + msize = 1; + is_signed = true; + break; + case "ldnt1w_z_p_ar_s_x32_unscaled"_h: + msize = 2; + break; + default: + VIXL_UNIMPLEMENTED(); + } + addr.SetMsizeInBytesLog2(msize); + SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed); +} + +void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + uint64_t xm = ReadXRegister(instr->GetRm()); + + LogicSVEAddressVector addr(xm, &zn, kFormatVnS); + VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_s_x32_unscaled"_h) || + (form_hash_ == "stnt1h_z_p_ar_s_x32_unscaled"_h) || + (form_hash_ == "stnt1w_z_p_ar_s_x32_unscaled"_h)); + + addr.SetMsizeInBytesLog2( + instr->GetSVEMsizeFromDtype(/* is_signed = */ false)); + SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr); +} + +void Simulator::VisitReserved(const Instruction* instr) { + // UDF is the only instruction in this group, and the Decoder is precise here. + VIXL_ASSERT(instr->Mask(ReservedMask) == UDF); + + printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n", + reinterpret_cast(instr), + instr->GetInstructionBits()); + VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n"); +} + + +void Simulator::VisitUnimplemented(const Instruction* instr) { + printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n", + reinterpret_cast(instr), + instr->GetInstructionBits()); + VIXL_UNIMPLEMENTED(); +} + + +void Simulator::VisitUnallocated(const Instruction* instr) { + printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n", + reinterpret_cast(instr), + instr->GetInstructionBits()); + VIXL_UNIMPLEMENTED(); +} + + +void Simulator::VisitPCRelAddressing(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) || + (instr->Mask(PCRelAddressingMask) == ADRP)); + + WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget()); +} + + +void Simulator::VisitUnconditionalBranch(const Instruction* instr) { + switch (instr->Mask(UnconditionalBranchMask)) { + case BL: + WriteLr(instr->GetNextInstruction()); + GCSPush(reinterpret_cast(instr->GetNextInstruction())); + VIXL_FALLTHROUGH(); + case B: + WritePc(instr->GetImmPCOffsetTarget()); + break; + default: + VIXL_UNREACHABLE(); + } +} + + +void Simulator::VisitConditionalBranch(const Instruction* instr) { + VIXL_ASSERT((form_hash_ == "b_only_condbranch"_h) || + (form_hash_ == "bc_only_condbranch"_h)); + if (ConditionPassed(instr->GetConditionBranch())) { + WritePc(instr->GetImmPCOffsetTarget()); + } +} + +BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const { + switch (instr->Mask(UnconditionalBranchToRegisterMask)) { + case BLR: + case BLRAA: + case BLRAB: + case BLRAAZ: + case BLRABZ: + return BranchAndLink; + case BR: + case BRAA: + case BRAB: + case BRAAZ: + case BRABZ: + if ((instr->GetRn() == 16) || (instr->GetRn() == 17) || + !PcIsInGuardedPage()) { + return BranchFromUnguardedOrToIP; + } + return BranchFromGuardedNotToIP; + } + return DefaultBType; +} + +void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) { + bool authenticate = false; + bool link = false; + bool ret = false; + bool compare_gcs = false; + uint64_t addr = ReadXRegister(instr->GetRn()); + uint64_t context = 0; + + switch (instr->Mask(UnconditionalBranchToRegisterMask)) { + case BLR: + link = true; + VIXL_FALLTHROUGH(); + case BR: + break; + + case BLRAAZ: + case BLRABZ: + link = true; + VIXL_FALLTHROUGH(); + case BRAAZ: + case BRABZ: + authenticate = true; + break; + + case BLRAA: + case BLRAB: + link = true; + VIXL_FALLTHROUGH(); + case BRAA: + case BRAB: + authenticate = true; + context = ReadXRegister(instr->GetRd()); + break; + + case RETAA: + case RETAB: + authenticate = true; + addr = ReadXRegister(kLinkRegCode); + context = ReadXRegister(31, Reg31IsStackPointer); + VIXL_FALLTHROUGH(); + case RET: + compare_gcs = true; + ret = true; + break; + default: + VIXL_UNREACHABLE(); + } + + if (authenticate) { + PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB; + addr = AuthPAC(addr, context, key, kInstructionPointer); + + int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2; + if (((addr >> error_lsb) & 0x3) != 0x0) { + VIXL_ABORT_WITH_MSG("Failed to authenticate pointer."); + } + } + + if (compare_gcs) { + uint64_t expected_lr = GCSPeek(); + char msg[128]; + if (expected_lr != 0) { + if ((expected_lr & 0x3) != 0) { + snprintf(msg, + sizeof(msg), + "GCS contains misaligned return address: 0x%016" PRIx64 "\n", + expected_lr); + ReportGCSFailure(msg); + } else if ((addr != 0) && (addr != expected_lr)) { + snprintf(msg, + sizeof(msg), + "GCS mismatch: lr = 0x%016" PRIx64 ", gcs = 0x%016" PRIx64 + "\n", + addr, + expected_lr); + ReportGCSFailure(msg); + } + GCSPop(); + } + } + + if (link) { + WriteLr(instr->GetNextInstruction()); + GCSPush(reinterpret_cast(instr->GetNextInstruction())); + } + + if (!ret) { + // Check for interceptions to the target address, if one is found, call it. + MetaDataDepot::BranchInterceptionAbstract* interception = + meta_data_.FindBranchInterception(addr); + + if (interception != nullptr) { + // Instead of writing the address of the function to the PC, call the + // function's interception directly. We change the address that will be + // branched to so that afterwards we continue execution from + // the address in the LR. Note: the interception may modify the LR so + // store it before calling the interception. + addr = ReadRegister(kLinkRegCode); + (*interception)(this); + } + } + + WriteNextBType(GetBTypeFromInstruction(instr)); + WritePc(Instruction::Cast(addr)); +} + + +void Simulator::VisitTestBranch(const Instruction* instr) { + unsigned bit_pos = + (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40(); + bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0; + bool take_branch = false; + switch (instr->Mask(TestBranchMask)) { + case TBZ: + take_branch = bit_zero; + break; + case TBNZ: + take_branch = !bit_zero; + break; + default: + VIXL_UNIMPLEMENTED(); + } + if (take_branch) { + WritePc(instr->GetImmPCOffsetTarget()); + } +} + + +void Simulator::VisitCompareBranch(const Instruction* instr) { + unsigned rt = instr->GetRt(); + bool take_branch = false; + switch (instr->Mask(CompareBranchMask)) { + case CBZ_w: + take_branch = (ReadWRegister(rt) == 0); + break; + case CBZ_x: + take_branch = (ReadXRegister(rt) == 0); + break; + case CBNZ_w: + take_branch = (ReadWRegister(rt) != 0); + break; + case CBNZ_x: + take_branch = (ReadXRegister(rt) != 0); + break; + default: + VIXL_UNIMPLEMENTED(); + } + if (take_branch) { + WritePc(instr->GetImmPCOffsetTarget()); + } +} + + +void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + bool set_flags = instr->GetFlagsUpdate(); + int64_t new_val = 0; + Instr operation = instr->Mask(AddSubOpMask); + + switch (operation) { + case ADD: + case ADDS: { + new_val = AddWithCarry(reg_size, + set_flags, + ReadRegister(reg_size, + instr->GetRn(), + instr->GetRnMode()), + op2); + break; + } + case SUB: + case SUBS: { + new_val = AddWithCarry(reg_size, + set_flags, + ReadRegister(reg_size, + instr->GetRn(), + instr->GetRnMode()), + ~op2, + 1); + break; + } + default: + VIXL_UNREACHABLE(); + } + + WriteRegister(reg_size, + instr->GetRd(), + new_val, + LogRegWrites, + instr->GetRdMode()); +} + + +void Simulator::VisitAddSubShifted(const Instruction* instr) { + // Add/sub/adds/subs don't allow ROR as a shift mode. + VIXL_ASSERT(instr->GetShiftDP() != ROR); + + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t op2 = ShiftOperand(reg_size, + ReadRegister(reg_size, instr->GetRm()), + static_cast(instr->GetShiftDP()), + instr->GetImmDPShift()); + AddSubHelper(instr, op2); +} + + +void Simulator::VisitAddSubImmediate(const Instruction* instr) { + int64_t op2 = instr->GetImmAddSub() + << ((instr->GetImmAddSubShift() == 1) ? 12 : 0); + AddSubHelper(instr, op2); +} + + +void Simulator::VisitAddSubExtended(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t op2 = ExtendValue(reg_size, + ReadRegister(reg_size, instr->GetRm()), + static_cast(instr->GetExtendMode()), + instr->GetImmExtendShift()); + AddSubHelper(instr, op2); +} + + +void Simulator::VisitAddSubWithCarry(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t op2 = ReadRegister(reg_size, instr->GetRm()); + int64_t new_val; + + if ((instr->Mask(AddSubOpMask) == SUB) || + (instr->Mask(AddSubOpMask) == SUBS)) { + op2 = ~op2; + } + + new_val = AddWithCarry(reg_size, + instr->GetFlagsUpdate(), + ReadRegister(reg_size, instr->GetRn()), + op2, + ReadC()); + + WriteRegister(reg_size, instr->GetRd(), new_val); +} + + +void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) { + switch (instr->Mask(RotateRightIntoFlagsMask)) { + case RMIF: { + uint64_t value = ReadRegister(instr->GetRn()); + unsigned shift = instr->GetImmRMIFRotation(); + unsigned mask = instr->GetNzcv(); + uint64_t rotated = RotateRight(value, shift, kXRegSize); + + ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask)); + LogSystemRegister(NZCV); + break; + } + } +} + + +void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) { + uint32_t value = ReadRegister(instr->GetRn()); + unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7; + + unsigned sign_bit = (value >> msb) & 1; + unsigned overflow_bit = (value >> (msb + 1)) & 1; + ReadNzcv().SetN(sign_bit); + ReadNzcv().SetZ((value << (31 - msb)) == 0); + ReadNzcv().SetV(sign_bit ^ overflow_bit); + LogSystemRegister(NZCV); +} + + +void Simulator::VisitLogicalShifted(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + Shift shift_type = static_cast(instr->GetShiftDP()); + unsigned shift_amount = instr->GetImmDPShift(); + int64_t op2 = ShiftOperand(reg_size, + ReadRegister(reg_size, instr->GetRm()), + shift_type, + shift_amount); + if (instr->Mask(NOT) == NOT) { + op2 = ~op2; + } + LogicalHelper(instr, op2); +} + + +void Simulator::VisitLogicalImmediate(const Instruction* instr) { + if (instr->GetImmLogical() == 0) { + VIXL_UNIMPLEMENTED(); + } else { + LogicalHelper(instr, instr->GetImmLogical()); + } +} + + +void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t op1 = ReadRegister(reg_size, instr->GetRn()); + int64_t result = 0; + bool update_flags = false; + + // Switch on the logical operation, stripping out the NOT bit, as it has a + // different meaning for logical immediate instructions. + switch (instr->Mask(LogicalOpMask & ~NOT)) { + case ANDS: + update_flags = true; + VIXL_FALLTHROUGH(); + case AND: + result = op1 & op2; + break; + case ORR: + result = op1 | op2; + break; + case EOR: + result = op1 ^ op2; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + if (update_flags) { + ReadNzcv().SetN(CalcNFlag(result, reg_size)); + ReadNzcv().SetZ(CalcZFlag(result)); + ReadNzcv().SetC(0); + ReadNzcv().SetV(0); + LogSystemRegister(NZCV); + } + + WriteRegister(reg_size, + instr->GetRd(), + result, + LogRegWrites, + instr->GetRdMode()); +} + + +void Simulator::VisitConditionalCompareRegister(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm())); +} + + +void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) { + ConditionalCompareHelper(instr, instr->GetImmCondCmp()); +} + + +void Simulator::ConditionalCompareHelper(const Instruction* instr, + int64_t op2) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t op1 = ReadRegister(reg_size, instr->GetRn()); + + if (ConditionPassed(instr->GetCondition())) { + // If the condition passes, set the status flags to the result of comparing + // the operands. + if (instr->Mask(ConditionalCompareMask) == CCMP) { + AddWithCarry(reg_size, true, op1, ~op2, 1); + } else { + VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN); + AddWithCarry(reg_size, true, op1, op2, 0); + } + } else { + // If the condition fails, set the status flags to the nzcv immediate. + ReadNzcv().SetFlags(instr->GetNzcv()); + LogSystemRegister(NZCV); + } +} + + +void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) { + int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS(); + LoadStoreHelper(instr, offset, Offset); +} + + +void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) { + LoadStoreHelper(instr, instr->GetImmLS(), Offset); +} + + +void Simulator::VisitLoadStorePreIndex(const Instruction* instr) { + LoadStoreHelper(instr, instr->GetImmLS(), PreIndex); +} + + +void Simulator::VisitLoadStorePostIndex(const Instruction* instr) { + LoadStoreHelper(instr, instr->GetImmLS(), PostIndex); +} + + +template +void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) { + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + unsigned element_size = sizeof(T2); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + int offset = instr->GetImmLS(); + address += offset; + + // Verify that the address is available to the host. + VIXL_ASSERT(address == static_cast(address)); + + // Check the alignment of `address`. + if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + + WriteRegister(rt, static_cast(value)); + + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + + LogRead(rt, GetPrintRegisterFormat(element_size), address); +} + + +template +void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) { + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + int offset = instr->GetImmLS(); + address += offset; + + // Verify that the address is available to the host. + VIXL_ASSERT(address == static_cast(address)); + + // Check the alignment of `address`. + if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + + // Approximate store-release by issuing a full barrier after the load. + VIXL_SYNC(); + + if (!MemWrite(address, ReadRegister(rt))) return; + + LogWrite(rt, GetPrintRegisterFormat(element_size), address); +} + + +void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) { + switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) { + case LDAPURB: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURH: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPUR_w: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPUR_x: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURSB_w: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURSB_x: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURSH_w: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURSH_x: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case LDAPURSW: + LoadAcquireRCpcUnscaledOffsetHelper(instr); + break; + case STLURB: + StoreReleaseUnscaledOffsetHelper(instr); + break; + case STLURH: + StoreReleaseUnscaledOffsetHelper(instr); + break; + case STLUR_w: + StoreReleaseUnscaledOffsetHelper(instr); + break; + case STLUR_x: + StoreReleaseUnscaledOffsetHelper(instr); + break; + } +} + + +void Simulator::VisitLoadStorePAC(const Instruction* instr) { + unsigned dst = instr->GetRt(); + unsigned addr_reg = instr->GetRn(); + + uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer); + + PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB; + address = AuthPAC(address, 0, key, kDataPointer); + + int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2; + if (((address >> error_lsb) & 0x3) != 0x0) { + VIXL_ABORT_WITH_MSG("Failed to authenticate pointer."); + } + + + if ((addr_reg == 31) && ((address % 16) != 0)) { + // When the base register is SP the stack pointer is required to be + // quadword aligned prior to the address calculation and write-backs. + // Misalignment will cause a stack alignment fault. + VIXL_ALIGNMENT_EXCEPTION(); + } + + int64_t offset = instr->GetImmLSPAC(); + address += offset; + + if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) { + // Pre-index mode. + VIXL_ASSERT(offset != 0); + WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer); + } + + uintptr_t addr_ptr = static_cast(address); + + // Verify that the calculated address is available to the host. + VIXL_ASSERT(address == addr_ptr); + + VIXL_DEFINE_OR_RETURN(value, MemRead(addr_ptr)); + + WriteXRegister(dst, value, NoRegLog); + unsigned access_size = 1 << 3; + LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr); +} + + +void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) { + Extend ext = static_cast(instr->GetExtendMode()); + VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); + unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS(); + + int64_t offset = + ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount); + LoadStoreHelper(instr, offset, Offset); +} + + +void Simulator::LoadStoreHelper(const Instruction* instr, + int64_t offset, + AddrMode addrmode) { + unsigned srcdst = instr->GetRt(); + uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode); + + bool rt_is_vreg = false; + int extend_to_size = 0; + LoadStoreOp op = static_cast(instr->Mask(LoadStoreMask)); + switch (op) { + case LDRB_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(srcdst, value, NoRegLog); + extend_to_size = kWRegSizeInBytes; + break; + } + case LDRH_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(srcdst, value, NoRegLog); + extend_to_size = kWRegSizeInBytes; + break; + } + case LDR_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(srcdst, value, NoRegLog); + extend_to_size = kWRegSizeInBytes; + break; + } + case LDR_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(srcdst, value, NoRegLog); + extend_to_size = kXRegSizeInBytes; + break; + } + case LDRSB_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(srcdst, value, NoRegLog); + extend_to_size = kWRegSizeInBytes; + break; + } + case LDRSH_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(srcdst, value, NoRegLog); + extend_to_size = kWRegSizeInBytes; + break; + } + case LDRSB_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(srcdst, value, NoRegLog); + extend_to_size = kXRegSizeInBytes; + break; + } + case LDRSH_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(srcdst, value, NoRegLog); + extend_to_size = kXRegSizeInBytes; + break; + } + case LDRSW_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(srcdst, value, NoRegLog); + extend_to_size = kXRegSizeInBytes; + break; + } + case LDR_b: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteBRegister(srcdst, value, NoRegLog); + rt_is_vreg = true; + break; + } + case LDR_h: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteHRegister(srcdst, value, NoRegLog); + rt_is_vreg = true; + break; + } + case LDR_s: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteSRegister(srcdst, value, NoRegLog); + rt_is_vreg = true; + break; + } + case LDR_d: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteDRegister(srcdst, value, NoRegLog); + rt_is_vreg = true; + break; + } + case LDR_q: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteQRegister(srcdst, value, NoRegLog); + rt_is_vreg = true; + break; + } + + case STRB_w: + if (!MemWrite(address, ReadWRegister(srcdst))) return; + break; + case STRH_w: + if (!MemWrite(address, ReadWRegister(srcdst))) return; + break; + case STR_w: + if (!MemWrite(address, ReadWRegister(srcdst))) return; + break; + case STR_x: + if (!MemWrite(address, ReadXRegister(srcdst))) return; + break; + case STR_b: + if (!MemWrite(address, ReadBRegister(srcdst))) return; + rt_is_vreg = true; + break; + case STR_h: + if (!MemWrite(address, ReadHRegisterBits(srcdst))) return; + rt_is_vreg = true; + break; + case STR_s: + if (!MemWrite(address, ReadSRegister(srcdst))) return; + rt_is_vreg = true; + break; + case STR_d: + if (!MemWrite(address, ReadDRegister(srcdst))) return; + rt_is_vreg = true; + break; + case STR_q: + if (!MemWrite(address, ReadQRegister(srcdst))) return; + rt_is_vreg = true; + break; + + // Ignore prfm hint instructions. + case PRFM: + break; + + default: + VIXL_UNIMPLEMENTED(); + } + + // Print a detailed trace (including the memory address). + bool extend = (extend_to_size != 0); + unsigned access_size = 1 << instr->GetSizeLS(); + unsigned result_size = extend ? extend_to_size : access_size; + PrintRegisterFormat print_format = + rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size) + : GetPrintRegisterFormatForSize(result_size); + + if (instr->IsLoad()) { + if (rt_is_vreg) { + LogVRead(srcdst, print_format, address); + } else { + LogExtendingRead(srcdst, print_format, access_size, address); + } + } else if (instr->IsStore()) { + if (rt_is_vreg) { + LogVWrite(srcdst, print_format, address); + } else { + LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address); + } + } else { + VIXL_ASSERT(op == PRFM); + } + + local_monitor_.MaybeClear(); +} + + +void Simulator::VisitLoadStorePairOffset(const Instruction* instr) { + LoadStorePairHelper(instr, Offset); +} + + +void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) { + LoadStorePairHelper(instr, PreIndex); +} + + +void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) { + LoadStorePairHelper(instr, PostIndex); +} + + +void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) { + LoadStorePairHelper(instr, Offset); +} + + +void Simulator::LoadStorePairHelper(const Instruction* instr, + AddrMode addrmode) { + unsigned rt = instr->GetRt(); + unsigned rt2 = instr->GetRt2(); + int element_size = 1 << instr->GetSizeLSPair(); + int64_t offset = instr->GetImmLSPair() * element_size; + uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode); + uintptr_t address2 = address + element_size; + + LoadStorePairOp op = + static_cast(instr->Mask(LoadStorePairMask)); + + // 'rt' and 'rt2' can only be aliased for stores. + VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2)); + + bool rt_is_vreg = false; + bool sign_extend = false; + switch (op) { + // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We + // will print a more detailed log. + case LDP_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteWRegister(rt, value, NoRegLog); + WriteWRegister(rt2, value2, NoRegLog); + break; + } + case LDP_s: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteSRegister(rt, value, NoRegLog); + WriteSRegister(rt2, value2, NoRegLog); + rt_is_vreg = true; + break; + } + case LDP_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteXRegister(rt, value, NoRegLog); + WriteXRegister(rt2, value2, NoRegLog); + break; + } + case LDP_d: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteDRegister(rt, value, NoRegLog); + WriteDRegister(rt2, value2, NoRegLog); + rt_is_vreg = true; + break; + } + case LDP_q: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteQRegister(rt, value, NoRegLog); + WriteQRegister(rt2, value2, NoRegLog); + rt_is_vreg = true; + break; + } + case LDPSW_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, MemRead(address2)); + WriteXRegister(rt, value, NoRegLog); + WriteXRegister(rt2, value2, NoRegLog); + sign_extend = true; + break; + } + case STP_w: { + if (!MemWrite(address, ReadWRegister(rt))) return; + if (!MemWrite(address2, ReadWRegister(rt2))) return; + break; + } + case STP_s: { + if (!MemWrite(address, ReadSRegister(rt))) return; + if (!MemWrite(address2, ReadSRegister(rt2))) return; + rt_is_vreg = true; + break; + } + case STP_x: { + if (!MemWrite(address, ReadXRegister(rt))) return; + if (!MemWrite(address2, ReadXRegister(rt2))) return; + break; + } + case STP_d: { + if (!MemWrite(address, ReadDRegister(rt))) return; + if (!MemWrite(address2, ReadDRegister(rt2))) return; + rt_is_vreg = true; + break; + } + case STP_q: { + if (!MemWrite(address, ReadQRegister(rt))) return; + if (!MemWrite(address2, ReadQRegister(rt2))) return; + rt_is_vreg = true; + break; + } + default: + VIXL_UNREACHABLE(); + } + + // Print a detailed trace (including the memory address). + unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size; + PrintRegisterFormat print_format = + rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size) + : GetPrintRegisterFormatForSize(result_size); + + if (instr->IsLoad()) { + if (rt_is_vreg) { + LogVRead(rt, print_format, address); + LogVRead(rt2, print_format, address2); + } else if (sign_extend) { + LogExtendingRead(rt, print_format, element_size, address); + LogExtendingRead(rt2, print_format, element_size, address2); + } else { + LogRead(rt, print_format, address); + LogRead(rt2, print_format, address2); + } + } else { + if (rt_is_vreg) { + LogVWrite(rt, print_format, address); + LogVWrite(rt2, print_format, address2); + } else { + LogWrite(rt, print_format, address); + LogWrite(rt2, print_format, address2); + } + } + + local_monitor_.MaybeClear(); +} + + +template +void Simulator::CompareAndSwapHelper(const Instruction* instr) { + unsigned rs = instr->GetRs(); + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, element_size); + + bool is_acquire = instr->ExtractBit(22) == 1; + bool is_release = instr->ExtractBit(15) == 1; + + T comparevalue = ReadRegister(rs); + T newvalue = ReadRegister(rt); + + // The architecture permits that the data read clears any exclusive monitors + // associated with that location, even if the compare subsequently fails. + local_monitor_.Clear(); + + VIXL_DEFINE_OR_RETURN(data, MemRead(address)); + + if (is_acquire) { + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + } + + if (data == comparevalue) { + if (is_release) { + // Approximate store-release by issuing a full barrier before the store. + VIXL_SYNC(); + } + if (!MemWrite(address, newvalue)) return; + LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address); + } + WriteRegister(rs, data, NoRegLog); + LogRead(rs, GetPrintRegisterFormatForSize(element_size), address); +} + + +template +void Simulator::CompareAndSwapPairHelper(const Instruction* instr) { + VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8)); + unsigned rs = instr->GetRs(); + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0)); + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2); + + uint64_t address2 = address + element_size; + + bool is_acquire = instr->ExtractBit(22) == 1; + bool is_release = instr->ExtractBit(15) == 1; + + T comparevalue_high = ReadRegister(rs + 1); + T comparevalue_low = ReadRegister(rs); + T newvalue_high = ReadRegister(rt + 1); + T newvalue_low = ReadRegister(rt); + + // The architecture permits that the data read clears any exclusive monitors + // associated with that location, even if the compare subsequently fails. + local_monitor_.Clear(); + + VIXL_DEFINE_OR_RETURN(data_low, MemRead(address)); + VIXL_DEFINE_OR_RETURN(data_high, MemRead(address2)); + + if (is_acquire) { + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + } + + bool same = + (data_high == comparevalue_high) && (data_low == comparevalue_low); + if (same) { + if (is_release) { + // Approximate store-release by issuing a full barrier before the store. + VIXL_SYNC(); + } + + if (!MemWrite(address, newvalue_low)) return; + if (!MemWrite(address2, newvalue_high)) return; + } + + WriteRegister(rs + 1, data_high, NoRegLog); + WriteRegister(rs, data_low, NoRegLog); + + PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size); + LogRead(rs, format, address); + LogRead(rs + 1, format, address2); + + if (same) { + LogWrite(rt, format, address); + LogWrite(rt + 1, format, address2); + } +} + +bool Simulator::CanReadMemory(uintptr_t address, size_t size) { +#ifndef _WIN32 + // To simulate fault-tolerant loads, we need to know what host addresses we + // can access without generating a real fault. One way to do that is to + // attempt to `write()` the memory to a placeholder pipe[1]. This is more + // portable and less intrusive than using (global) signal handlers. + // + // [1]: https://stackoverflow.com/questions/7134590 + + size_t written = 0; + bool can_read = true; + // `write` will normally return after one invocation, but it is allowed to + // handle only part of the operation, so wrap it in a loop. + while (can_read && (written < size)) { + ssize_t result = write(placeholder_pipe_fd_[1], + reinterpret_cast(address + written), + size - written); + if (result > 0) { + written += result; + } else { + switch (result) { + case -EPERM: + case -EFAULT: + // The address range is not accessible. + // `write` is supposed to return -EFAULT in this case, but in practice + // it seems to return -EPERM, so we accept that too. + can_read = false; + break; + case -EINTR: + // The call was interrupted by a signal. Just try again. + break; + default: + // Any other error is fatal. + VIXL_ABORT(); + } + } + } + // Drain the read side of the pipe. If we don't do this, we'll leak memory as + // the placeholder data is buffered. As before, we expect to drain the whole + // write in one invocation, but cannot guarantee that, so we wrap it in a + // loop. This function is primarily intended to implement SVE fault-tolerant + // loads, so the maximum Z register size is a good default buffer size. + char buffer[kZRegMaxSizeInBytes]; + while (written > 0) { + ssize_t result = read(placeholder_pipe_fd_[0], + reinterpret_cast(buffer), + sizeof(buffer)); + // `read` blocks, and returns 0 only at EOF. We should not hit EOF until + // we've read everything that was written, so treat 0 as an error. + if (result > 0) { + VIXL_ASSERT(static_cast(result) <= written); + written -= result; + } else { + // For -EINTR, just try again. We can't handle any other error. + VIXL_CHECK(result == -EINTR); + } + } + + return can_read; +#else + // To simulate fault-tolerant loads, we need to know what host addresses we + // can access without generating a real fault + // The pipe code above is almost but not fully compatible with Windows + // Instead, use the platform specific API VirtualQuery() + // + // [2]: https://stackoverflow.com/a/18395247/9109981 + + bool can_read = true; + MEMORY_BASIC_INFORMATION pageInfo; + + size_t checked = 0; + while (can_read && (checked < size)) { + size_t result = VirtualQuery(reinterpret_cast(address + checked), + &pageInfo, + sizeof(pageInfo)); + + if (result < 0) { + can_read = false; + break; + } + + if (pageInfo.State != MEM_COMMIT) { + can_read = false; + break; + } + + if (pageInfo.Protect == PAGE_NOACCESS || pageInfo.Protect == PAGE_EXECUTE) { + can_read = false; + break; + } + checked += pageInfo.RegionSize - + ((address + checked) - + reinterpret_cast(pageInfo.BaseAddress)); + } + + return can_read; +#endif +} + +void Simulator::PrintExclusiveAccessWarning() { + if (print_exclusive_access_warning_) { + fprintf(stderr, + "%sWARNING:%s VIXL simulator support for " + "load-/store-/clear-exclusive " + "instructions is limited. Refer to the README for details.%s\n", + clr_warning, + clr_warning_message, + clr_normal); + print_exclusive_access_warning_ = false; + } +} + +void Simulator::VisitLoadStoreExclusive(const Instruction* instr) { + LoadStoreExclusive op = + static_cast(instr->Mask(LoadStoreExclusiveMask)); + + switch (op) { + case CAS_w: + case CASA_w: + case CASL_w: + case CASAL_w: + CompareAndSwapHelper(instr); + break; + case CAS_x: + case CASA_x: + case CASL_x: + case CASAL_x: + CompareAndSwapHelper(instr); + break; + case CASB: + case CASAB: + case CASLB: + case CASALB: + CompareAndSwapHelper(instr); + break; + case CASH: + case CASAH: + case CASLH: + case CASALH: + CompareAndSwapHelper(instr); + break; + case CASP_w: + case CASPA_w: + case CASPL_w: + case CASPAL_w: + CompareAndSwapPairHelper(instr); + break; + case CASP_x: + case CASPA_x: + case CASPL_x: + case CASPAL_x: + CompareAndSwapPairHelper(instr); + break; + default: + PrintExclusiveAccessWarning(); + + unsigned rs = instr->GetRs(); + unsigned rt = instr->GetRt(); + unsigned rt2 = instr->GetRt2(); + unsigned rn = instr->GetRn(); + + bool is_exclusive = !instr->GetLdStXNotExclusive(); + bool is_acquire_release = + !is_exclusive || instr->GetLdStXAcquireRelease(); + bool is_load = instr->GetLdStXLoad(); + bool is_pair = instr->GetLdStXPair(); + + unsigned element_size = 1 << instr->GetLdStXSizeLog2(); + unsigned access_size = is_pair ? element_size * 2 : element_size; + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, access_size); + + if (is_load) { + if (is_exclusive) { + local_monitor_.MarkExclusive(address, access_size); + } else { + // Any non-exclusive load can clear the local monitor as a side + // effect. We don't need to do this, but it is useful to stress the + // simulated code. + local_monitor_.Clear(); + } + + // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). + // We will print a more detailed log. + unsigned reg_size = 0; + switch (op) { + case LDXRB_w: + case LDAXRB_w: + case LDARB_w: + case LDLARB: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(rt, value, NoRegLog); + reg_size = kWRegSizeInBytes; + break; + } + case LDXRH_w: + case LDAXRH_w: + case LDARH_w: + case LDLARH: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(rt, value, NoRegLog); + reg_size = kWRegSizeInBytes; + break; + } + case LDXR_w: + case LDAXR_w: + case LDAR_w: + case LDLAR_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(rt, value, NoRegLog); + reg_size = kWRegSizeInBytes; + break; + } + case LDXR_x: + case LDAXR_x: + case LDAR_x: + case LDLAR_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(rt, value, NoRegLog); + reg_size = kXRegSizeInBytes; + break; + } + case LDXP_w: + case LDAXP_w: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, + MemRead(address + element_size)); + WriteWRegister(rt, value, NoRegLog); + WriteWRegister(rt2, value2, NoRegLog); + reg_size = kWRegSizeInBytes; + break; + } + case LDXP_x: + case LDAXP_x: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + VIXL_DEFINE_OR_RETURN(value2, + MemRead(address + element_size)); + WriteXRegister(rt, value, NoRegLog); + WriteXRegister(rt2, value2, NoRegLog); + reg_size = kXRegSizeInBytes; + break; + } + default: + VIXL_UNREACHABLE(); + } + + if (is_acquire_release) { + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + } + + PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size); + LogExtendingRead(rt, format, element_size, address); + if (is_pair) { + LogExtendingRead(rt2, format, element_size, address + element_size); + } + } else { + if (is_acquire_release) { + // Approximate store-release by issuing a full barrier before the + // store. + VIXL_SYNC(); + } + + bool do_store = true; + if (is_exclusive) { + do_store = local_monitor_.IsExclusive(address, access_size) && + global_monitor_.IsExclusive(address, access_size); + WriteWRegister(rs, do_store ? 0 : 1); + + // - All exclusive stores explicitly clear the local monitor. + local_monitor_.Clear(); + } else { + // - Any other store can clear the local monitor as a side effect. + local_monitor_.MaybeClear(); + } + + if (do_store) { + switch (op) { + case STXRB_w: + case STLXRB_w: + case STLRB_w: + case STLLRB: + if (!MemWrite(address, ReadWRegister(rt))) return; + break; + case STXRH_w: + case STLXRH_w: + case STLRH_w: + case STLLRH: + if (!MemWrite(address, ReadWRegister(rt))) return; + break; + case STXR_w: + case STLXR_w: + case STLR_w: + case STLLR_w: + if (!MemWrite(address, ReadWRegister(rt))) return; + break; + case STXR_x: + case STLXR_x: + case STLR_x: + case STLLR_x: + if (!MemWrite(address, ReadXRegister(rt))) return; + break; + case STXP_w: + case STLXP_w: + if (!MemWrite(address, ReadWRegister(rt))) return; + if (!MemWrite(address + element_size, + ReadWRegister(rt2))) { + return; + } + break; + case STXP_x: + case STLXP_x: + if (!MemWrite(address, ReadXRegister(rt))) return; + if (!MemWrite(address + element_size, + ReadXRegister(rt2))) { + return; + } + break; + default: + VIXL_UNREACHABLE(); + } + + PrintRegisterFormat format = + GetPrintRegisterFormatForSize(element_size); + LogWrite(rt, format, address); + if (is_pair) { + LogWrite(rt2, format, address + element_size); + } + } + } + } +} + +template +void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) { + unsigned rs = instr->GetRs(); + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode); + bool is_release = instr->ExtractBit(22) == 1; + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, element_size); + + T value = ReadRegister(rs); + + VIXL_DEFINE_OR_RETURN(data, MemRead(address)); + + if (is_acquire) { + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + } + + T result = 0; + switch (instr->Mask(AtomicMemorySimpleOpMask)) { + case LDADDOp: + result = data + value; + break; + case LDCLROp: + VIXL_ASSERT(!std::numeric_limits::is_signed); + result = data & ~value; + break; + case LDEOROp: + VIXL_ASSERT(!std::numeric_limits::is_signed); + result = data ^ value; + break; + case LDSETOp: + VIXL_ASSERT(!std::numeric_limits::is_signed); + result = data | value; + break; + + // Signed/Unsigned difference is done via the templated type T. + case LDSMAXOp: + case LDUMAXOp: + result = (data > value) ? data : value; + break; + case LDSMINOp: + case LDUMINOp: + result = (data > value) ? value : data; + break; + } + + if (is_release) { + // Approximate store-release by issuing a full barrier before the store. + VIXL_SYNC(); + } + + WriteRegister(rt, data, NoRegLog); + + unsigned register_size = element_size; + if (element_size < kXRegSizeInBytes) { + register_size = kWRegSizeInBytes; + } + PrintRegisterFormat format = GetPrintRegisterFormatForSize(register_size); + LogExtendingRead(rt, format, element_size, address); + + if (!MemWrite(address, result)) return; + format = GetPrintRegisterFormatForSize(element_size); + LogWrite(rs, format, address); +} + +template +void Simulator::AtomicMemorySwapHelper(const Instruction* instr) { + unsigned rs = instr->GetRs(); + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode); + bool is_release = instr->ExtractBit(22) == 1; + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, element_size); + + VIXL_DEFINE_OR_RETURN(data, MemRead(address)); + + if (is_acquire) { + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + } + + if (is_release) { + // Approximate store-release by issuing a full barrier before the store. + VIXL_SYNC(); + } + if (!MemWrite(address, ReadRegister(rs))) return; + + WriteRegister(rt, data); + + PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size); + LogRead(rt, format, address); + LogWrite(rs, format, address); +} + +template +void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) { + unsigned rt = instr->GetRt(); + unsigned rn = instr->GetRn(); + + unsigned element_size = sizeof(T); + uint64_t address = ReadRegister(rn, Reg31IsStackPointer); + + CheckIsValidUnalignedAtomicAccess(rn, address, element_size); + + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + + WriteRegister(rt, value); + + // Approximate load-acquire by issuing a full barrier after the load. + VIXL_SYNC(); + + LogRead(rt, GetPrintRegisterFormatForSize(element_size), address); +} + +#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \ + V(LDADD) \ + V(LDCLR) \ + V(LDEOR) \ + V(LDSET) \ + V(LDUMAX) \ + V(LDUMIN) + +#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \ + V(LDSMAX) \ + V(LDSMIN) + +void Simulator::VisitAtomicMemory(const Instruction* instr) { + switch (instr->Mask(AtomicMemoryMask)) { +// clang-format off +#define SIM_FUNC_B(A) \ + case A##B: \ + case A##AB: \ + case A##LB: \ + case A##ALB: +#define SIM_FUNC_H(A) \ + case A##H: \ + case A##AH: \ + case A##LH: \ + case A##ALH: +#define SIM_FUNC_w(A) \ + case A##_w: \ + case A##A_w: \ + case A##L_w: \ + case A##AL_w: +#define SIM_FUNC_x(A) \ + case A##_x: \ + case A##A_x: \ + case A##L_x: \ + case A##AL_x: + + ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x) + AtomicMemorySimpleHelper(instr); + break; + ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x) + AtomicMemorySimpleHelper(instr); + break; + // clang-format on + + case SWPB: + case SWPAB: + case SWPLB: + case SWPALB: + AtomicMemorySwapHelper(instr); + break; + case SWPH: + case SWPAH: + case SWPLH: + case SWPALH: + AtomicMemorySwapHelper(instr); + break; + case SWP_w: + case SWPA_w: + case SWPL_w: + case SWPAL_w: + AtomicMemorySwapHelper(instr); + break; + case SWP_x: + case SWPA_x: + case SWPL_x: + case SWPAL_x: + AtomicMemorySwapHelper(instr); + break; + case LDAPRB: + LoadAcquireRCpcHelper(instr); + break; + case LDAPRH: + LoadAcquireRCpcHelper(instr); + break; + case LDAPR_w: + LoadAcquireRCpcHelper(instr); + break; + case LDAPR_x: + LoadAcquireRCpcHelper(instr); + break; + } +} + + +void Simulator::VisitLoadLiteral(const Instruction* instr) { + unsigned rt = instr->GetRt(); + uint64_t address = instr->GetLiteralAddress(); + + // Verify that the calculated address is available to the host. + VIXL_ASSERT(address == static_cast(address)); + + switch (instr->Mask(LoadLiteralMask)) { + // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then + // print a more detailed log. + case LDR_w_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteWRegister(rt, value, NoRegLog); + LogRead(rt, kPrintWReg, address); + break; + } + case LDR_x_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(rt, value, NoRegLog); + LogRead(rt, kPrintXReg, address); + break; + } + case LDR_s_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteSRegister(rt, value, NoRegLog); + LogVRead(rt, kPrintSRegFP, address); + break; + } + case LDR_d_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteDRegister(rt, value, NoRegLog); + LogVRead(rt, kPrintDRegFP, address); + break; + } + case LDR_q_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteQRegister(rt, value, NoRegLog); + LogVRead(rt, kPrintReg1Q, address); + break; + } + case LDRSW_x_lit: { + VIXL_DEFINE_OR_RETURN(value, MemRead(address)); + WriteXRegister(rt, value, NoRegLog); + LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address); + break; + } + + // Ignore prfm hint instructions. + case PRFM_lit: + break; + + default: + VIXL_UNREACHABLE(); + } + + local_monitor_.MaybeClear(); +} + + +uintptr_t Simulator::AddressModeHelper(unsigned addr_reg, + int64_t offset, + AddrMode addrmode) { + uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer); + + if ((addr_reg == 31) && ((address % 16) != 0)) { + // When the base register is SP the stack pointer is required to be + // quadword aligned prior to the address calculation and write-backs. + // Misalignment will cause a stack alignment fault. + VIXL_ALIGNMENT_EXCEPTION(); + } + + if ((addrmode == PreIndex) || (addrmode == PostIndex)) { + VIXL_ASSERT(offset != 0); + // Only preindex should log the register update here. For Postindex, the + // update will be printed automatically by LogWrittenRegisters _after_ the + // memory access itself is logged. + RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog; + WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer); + } + + if ((addrmode == Offset) || (addrmode == PreIndex)) { + address += offset; + } + + // Verify that the calculated address is available to the host. + VIXL_ASSERT(address == static_cast(address)); + + return static_cast(address); +} + + +void Simulator::VisitMoveWideImmediate(const Instruction* instr) { + MoveWideImmediateOp mov_op = + static_cast(instr->Mask(MoveWideImmediateMask)); + int64_t new_xn_val = 0; + + bool is_64_bits = instr->GetSixtyFourBits() == 1; + // Shift is limited for W operations. + VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2)); + + // Get the shifted immediate. + int64_t shift = instr->GetShiftMoveWide() * 16; + int64_t shifted_imm16 = static_cast(instr->GetImmMoveWide()) + << shift; + + // Compute the new value. + switch (mov_op) { + case MOVN_w: + case MOVN_x: { + new_xn_val = ~shifted_imm16; + if (!is_64_bits) new_xn_val &= kWRegMask; + break; + } + case MOVK_w: + case MOVK_x: { + unsigned reg_code = instr->GetRd(); + int64_t prev_xn_val = + is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code); + new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16; + break; + } + case MOVZ_w: + case MOVZ_x: { + new_xn_val = shifted_imm16; + break; + } + default: + VIXL_UNREACHABLE(); + } + + // Update the destination register. + WriteXRegister(instr->GetRd(), new_xn_val); +} + + +void Simulator::VisitConditionalSelect(const Instruction* instr) { + uint64_t new_val = ReadXRegister(instr->GetRn()); + + if (ConditionFailed(static_cast(instr->GetCondition()))) { + new_val = ReadXRegister(instr->GetRm()); + switch (instr->Mask(ConditionalSelectMask)) { + case CSEL_w: + case CSEL_x: + break; + case CSINC_w: + case CSINC_x: + new_val++; + break; + case CSINV_w: + case CSINV_x: + new_val = ~new_val; + break; + case CSNEG_w: + case CSNEG_x: + new_val = UnsignedNegate(new_val); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + WriteRegister(reg_size, instr->GetRd(), new_val); +} + + +#define PAUTH_MODES_REGISTER_CONTEXT(V) \ + V(i, a, kPACKeyIA, kInstructionPointer) \ + V(i, b, kPACKeyIB, kInstructionPointer) \ + V(d, a, kPACKeyDA, kDataPointer) \ + V(d, b, kPACKeyDB, kDataPointer) + +void Simulator::VisitDataProcessing1Source(const Instruction* instr) { + unsigned dst = instr->GetRd(); + unsigned src = instr->GetRn(); + Reg31Mode r31_pac = Reg31IsStackPointer; + + switch (form_hash_) { +#define DEFINE_PAUTH_FUNCS(SUF0, SUF1, KEY, D) \ + case "pac" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \ + VIXL_ASSERT(src == kZeroRegCode); \ + r31_pac = Reg31IsZeroRegister; \ + VIXL_FALLTHROUGH(); \ + case "pac" #SUF0 #SUF1 "_64p_dp_1src"_h: { \ + uint64_t mod = ReadXRegister(src, r31_pac); \ + uint64_t ptr = ReadXRegister(dst); \ + WriteXRegister(dst, AddPAC(ptr, mod, KEY, D)); \ + break; \ + } \ + case "aut" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \ + VIXL_ASSERT(src == kZeroRegCode); \ + r31_pac = Reg31IsZeroRegister; \ + VIXL_FALLTHROUGH(); \ + case "aut" #SUF0 #SUF1 "_64p_dp_1src"_h: { \ + uint64_t mod = ReadXRegister(src, r31_pac); \ + uint64_t ptr = ReadXRegister(dst); \ + WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \ + break; \ + } + PAUTH_MODES_REGISTER_CONTEXT(DEFINE_PAUTH_FUNCS) +#undef DEFINE_PAUTH_FUNCS + + case "xpaci_64z_dp_1src"_h: + WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer)); + break; + case "xpacd_64z_dp_1src"_h: + WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer)); + break; + case "rbit_32_dp_1src"_h: + WriteWRegister(dst, ReverseBits(ReadWRegister(src))); + break; + case "rbit_64_dp_1src"_h: + WriteXRegister(dst, ReverseBits(ReadXRegister(src))); + break; + case "rev16_32_dp_1src"_h: + WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1)); + break; + case "rev16_64_dp_1src"_h: + WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1)); + break; + case "rev_32_dp_1src"_h: + WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2)); + break; + case "rev32_64_dp_1src"_h: + WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2)); + break; + case "rev_64_dp_1src"_h: + WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3)); + break; + case "clz_32_dp_1src"_h: + WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src))); + break; + case "clz_64_dp_1src"_h: + WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src))); + break; + case "cls_32_dp_1src"_h: + WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src))); + break; + case "cls_64_dp_1src"_h: + WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src))); + break; + case "abs_32_dp_1src"_h: + WriteWRegister(dst, Abs(ReadWRegister(src))); + break; + case "abs_64_dp_1src"_h: + WriteXRegister(dst, Abs(ReadXRegister(src))); + break; + case "cnt_32_dp_1src"_h: + WriteWRegister(dst, CountSetBits(ReadWRegister(src))); + break; + case "cnt_64_dp_1src"_h: + WriteXRegister(dst, CountSetBits(ReadXRegister(src))); + break; + case "ctz_32_dp_1src"_h: + WriteWRegister(dst, CountTrailingZeros(ReadWRegister(src))); + break; + case "ctz_64_dp_1src"_h: + WriteXRegister(dst, CountTrailingZeros(ReadXRegister(src))); + break; + } +} + +uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) { + VIXL_ASSERT((n > 32) && (n <= 64)); + for (unsigned i = (n - 1); i >= 32; i--) { + if (((data >> i) & 1) != 0) { + uint64_t polysh32 = (uint64_t)poly << (i - 32); + uint64_t mask = (UINT64_C(1) << i) - 1; + data = ((data & mask) ^ polysh32); + } + } + return data & 0xffffffff; +} + + +template +uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) { + unsigned size = sizeof(val) * 8; // Number of bits in type T. + VIXL_ASSERT((size == 8) || (size == 16) || (size == 32)); + uint64_t tempacc = static_cast(ReverseBits(acc)) << size; + uint64_t tempval = static_cast(ReverseBits(val)) << 32; + return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly)); +} + + +uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) { + // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute + // the CRC of each 32-bit word sequentially. + acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly); + return Crc32Checksum(acc, (uint32_t)(val >> 32), poly); +} + + +void Simulator::VisitDataProcessing2Source(const Instruction* instr) { + Shift shift_op = NO_SHIFT; + int64_t result = 0; + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + + switch (instr->Mask(DataProcessing2SourceMask)) { + case SDIV_w: { + int32_t rn = ReadWRegister(instr->GetRn()); + int32_t rm = ReadWRegister(instr->GetRm()); + if ((rn == kWMinInt) && (rm == -1)) { + result = kWMinInt; + } else if (rm == 0) { + // Division by zero can be trapped, but not on A-class processors. + result = 0; + } else { + result = rn / rm; + } + break; + } + case SDIV_x: { + int64_t rn = ReadXRegister(instr->GetRn()); + int64_t rm = ReadXRegister(instr->GetRm()); + if ((rn == kXMinInt) && (rm == -1)) { + result = kXMinInt; + } else if (rm == 0) { + // Division by zero can be trapped, but not on A-class processors. + result = 0; + } else { + result = rn / rm; + } + break; + } + case UDIV_w: { + uint32_t rn = static_cast(ReadWRegister(instr->GetRn())); + uint32_t rm = static_cast(ReadWRegister(instr->GetRm())); + if (rm == 0) { + // Division by zero can be trapped, but not on A-class processors. + result = 0; + } else { + result = rn / rm; + } + break; + } + case UDIV_x: { + uint64_t rn = static_cast(ReadXRegister(instr->GetRn())); + uint64_t rm = static_cast(ReadXRegister(instr->GetRm())); + if (rm == 0) { + // Division by zero can be trapped, but not on A-class processors. + result = 0; + } else { + result = rn / rm; + } + break; + } + case LSLV_w: + case LSLV_x: + shift_op = LSL; + break; + case LSRV_w: + case LSRV_x: + shift_op = LSR; + break; + case ASRV_w: + case ASRV_x: + shift_op = ASR; + break; + case RORV_w: + case RORV_x: + shift_op = ROR; + break; + case PACGA: { + uint64_t dst = static_cast(ReadXRegister(instr->GetRn())); + uint64_t src = static_cast( + ReadXRegister(instr->GetRm(), Reg31IsStackPointer)); + uint64_t code = ComputePAC(dst, src, kPACKeyGA); + result = code & 0xffffffff00000000; + break; + } + case CRC32B: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint8_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32_POLY); + break; + } + case CRC32H: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint16_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32_POLY); + break; + } + case CRC32W: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint32_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32_POLY); + break; + } + case CRC32X: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint64_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32_POLY); + reg_size = kWRegSize; + break; + } + case CRC32CB: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint8_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32C_POLY); + break; + } + case CRC32CH: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint16_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32C_POLY); + break; + } + case CRC32CW: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint32_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32C_POLY); + break; + } + case CRC32CX: { + uint32_t acc = ReadRegister(instr->GetRn()); + uint64_t val = ReadRegister(instr->GetRm()); + result = Crc32Checksum(acc, val, CRC32C_POLY); + reg_size = kWRegSize; + break; + } + default: + VIXL_UNIMPLEMENTED(); + } + + if (shift_op != NO_SHIFT) { + // Shift distance encoded in the least-significant five/six bits of the + // register. + int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f; + unsigned shift = ReadWRegister(instr->GetRm()) & mask; + result = ShiftOperand(reg_size, + ReadRegister(reg_size, instr->GetRn()), + shift_op, + shift); + } + WriteRegister(reg_size, instr->GetRd(), result); +} + +void Simulator::SimulateSignedMinMax(const Instruction* instr) { + int32_t wn = ReadWRegister(instr->GetRn()); + int32_t wm = ReadWRegister(instr->GetRm()); + int64_t xn = ReadXRegister(instr->GetRn()); + int64_t xm = ReadXRegister(instr->GetRm()); + int32_t imm = instr->ExtractSignedBits(17, 10); + int dst = instr->GetRd(); + + switch (form_hash_) { + case "smax_64_minmax_imm"_h: + case "smin_64_minmax_imm"_h: + xm = imm; + break; + case "smax_32_minmax_imm"_h: + case "smin_32_minmax_imm"_h: + wm = imm; + break; + } + + switch (form_hash_) { + case "smax_32_minmax_imm"_h: + case "smax_32_dp_2src"_h: + WriteWRegister(dst, std::max(wn, wm)); + break; + case "smax_64_minmax_imm"_h: + case "smax_64_dp_2src"_h: + WriteXRegister(dst, std::max(xn, xm)); + break; + case "smin_32_minmax_imm"_h: + case "smin_32_dp_2src"_h: + WriteWRegister(dst, std::min(wn, wm)); + break; + case "smin_64_minmax_imm"_h: + case "smin_64_dp_2src"_h: + WriteXRegister(dst, std::min(xn, xm)); + break; + } +} + +void Simulator::SimulateUnsignedMinMax(const Instruction* instr) { + uint64_t xn = ReadXRegister(instr->GetRn()); + uint64_t xm = ReadXRegister(instr->GetRm()); + uint32_t imm = instr->ExtractBits(17, 10); + int dst = instr->GetRd(); + + switch (form_hash_) { + case "umax_64u_minmax_imm"_h: + case "umax_32u_minmax_imm"_h: + case "umin_64u_minmax_imm"_h: + case "umin_32u_minmax_imm"_h: + xm = imm; + break; + } + + switch (form_hash_) { + case "umax_32u_minmax_imm"_h: + case "umax_32_dp_2src"_h: + xn &= 0xffff'ffff; + xm &= 0xffff'ffff; + VIXL_FALLTHROUGH(); + case "umax_64u_minmax_imm"_h: + case "umax_64_dp_2src"_h: + WriteXRegister(dst, std::max(xn, xm)); + break; + case "umin_32u_minmax_imm"_h: + case "umin_32_dp_2src"_h: + xn &= 0xffff'ffff; + xm &= 0xffff'ffff; + VIXL_FALLTHROUGH(); + case "umin_64u_minmax_imm"_h: + case "umin_64_dp_2src"_h: + WriteXRegister(dst, std::min(xn, xm)); + break; + } +} + +void Simulator::VisitDataProcessing3Source(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + + uint64_t result = 0; + // Extract and sign- or zero-extend 32-bit arguments for widening operations. + uint64_t rn_u32 = ReadRegister(instr->GetRn()); + uint64_t rm_u32 = ReadRegister(instr->GetRm()); + int64_t rn_s32 = ReadRegister(instr->GetRn()); + int64_t rm_s32 = ReadRegister(instr->GetRm()); + uint64_t rn_u64 = ReadXRegister(instr->GetRn()); + uint64_t rm_u64 = ReadXRegister(instr->GetRm()); + switch (instr->Mask(DataProcessing3SourceMask)) { + case MADD_w: + case MADD_x: + result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64); + break; + case MSUB_w: + case MSUB_x: + result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64); + break; + case SMADDL_x: + result = ReadXRegister(instr->GetRa()) + + static_cast(rn_s32 * rm_s32); + break; + case SMSUBL_x: + result = ReadXRegister(instr->GetRa()) - + static_cast(rn_s32 * rm_s32); + break; + case UMADDL_x: + result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32); + break; + case UMSUBL_x: + result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32); + break; + case UMULH_x: + result = + internal::MultiplyHigh<64>(ReadRegister(instr->GetRn()), + ReadRegister(instr->GetRm())); + break; + case SMULH_x: + result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()), + ReadXRegister(instr->GetRm())); + break; + default: + VIXL_UNIMPLEMENTED(); + } + WriteRegister(reg_size, instr->GetRd(), result); +} + + +void Simulator::VisitBitfield(const Instruction* instr) { + unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize; + int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask; + int R = instr->GetImmR(); + int S = instr->GetImmS(); + + int diff = S - R; + uint64_t mask; + if (diff >= 0) { + mask = ~UINT64_C(0) >> (64 - (diff + 1)); + mask = (static_cast(diff) < (reg_size - 1)) ? mask : reg_mask; + } else { + mask = ~UINT64_C(0) >> (64 - (S + 1)); + mask = RotateRight(mask, R, reg_size); + diff += reg_size; + } + + // inzero indicates if the extracted bitfield is inserted into the + // destination register value or in zero. + // If extend is true, extend the sign of the extracted bitfield. + bool inzero = false; + bool extend = false; + switch (instr->Mask(BitfieldMask)) { + case BFM_x: + case BFM_w: + break; + case SBFM_x: + case SBFM_w: + inzero = true; + extend = true; + break; + case UBFM_x: + case UBFM_w: + inzero = true; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd()); + uint64_t src = ReadRegister(reg_size, instr->GetRn()); + // Rotate source bitfield into place. + uint64_t result = RotateRight(src, R, reg_size); + // Determine the sign extension. + uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1)); + uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0; + + // Merge sign extension, dest/zero and bitfield. + result = signbits | (result & mask) | (dst & ~mask); + + WriteRegister(reg_size, instr->GetRd(), result); +} + + +void Simulator::VisitExtract(const Instruction* instr) { + unsigned lsb = instr->GetImmS(); + unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize; + uint64_t low_res = + static_cast(ReadRegister(reg_size, instr->GetRm())) >> lsb; + uint64_t high_res = (lsb == 0) + ? 0 + : ReadRegister(reg_size, instr->GetRn()) + << (reg_size - lsb); + WriteRegister(reg_size, instr->GetRd(), low_res | high_res); +} + + +void Simulator::VisitFPImmediate(const Instruction* instr) { + AssertSupportedFPCR(); + unsigned dest = instr->GetRd(); + switch (instr->Mask(FPImmediateMask)) { + case FMOV_h_imm: + WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16())); + break; + case FMOV_s_imm: + WriteSRegister(dest, instr->GetImmFP32()); + break; + case FMOV_d_imm: + WriteDRegister(dest, instr->GetImmFP64()); + break; + default: + VIXL_UNREACHABLE(); + } +} + + +void Simulator::VisitFPIntegerConvert(const Instruction* instr) { + AssertSupportedFPCR(); + + unsigned dst = instr->GetRd(); + unsigned src = instr->GetRn(); + + FPRounding round = ReadRMode(); + + switch (instr->Mask(FPIntegerConvertMask)) { + case FCVTAS_wh: + WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway)); + break; + case FCVTAS_xh: + WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway)); + break; + case FCVTAS_ws: + WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway)); + break; + case FCVTAS_xs: + WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway)); + break; + case FCVTAS_wd: + WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway)); + break; + case FCVTAS_xd: + WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway)); + break; + case FCVTAU_wh: + WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway)); + break; + case FCVTAU_xh: + WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway)); + break; + case FCVTAU_ws: + WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway)); + break; + case FCVTAU_xs: + WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway)); + break; + case FCVTAU_wd: + WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway)); + break; + case FCVTAU_xd: + WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway)); + break; + case FCVTMS_wh: + WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity)); + break; + case FCVTMS_xh: + WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity)); + break; + case FCVTMS_ws: + WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity)); + break; + case FCVTMS_xs: + WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity)); + break; + case FCVTMS_wd: + WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity)); + break; + case FCVTMS_xd: + WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_wh: + WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_xh: + WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_ws: + WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_xs: + WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_wd: + WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity)); + break; + case FCVTMU_xd: + WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity)); + break; + case FCVTPS_wh: + WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity)); + break; + case FCVTPS_xh: + WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity)); + break; + case FCVTPS_ws: + WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity)); + break; + case FCVTPS_xs: + WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity)); + break; + case FCVTPS_wd: + WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity)); + break; + case FCVTPS_xd: + WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_wh: + WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_xh: + WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_ws: + WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_xs: + WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_wd: + WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity)); + break; + case FCVTPU_xd: + WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity)); + break; + case FCVTNS_wh: + WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven)); + break; + case FCVTNS_xh: + WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven)); + break; + case FCVTNS_ws: + WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven)); + break; + case FCVTNS_xs: + WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven)); + break; + case FCVTNS_wd: + WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven)); + break; + case FCVTNS_xd: + WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven)); + break; + case FCVTNU_wh: + WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven)); + break; + case FCVTNU_xh: + WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven)); + break; + case FCVTNU_ws: + WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven)); + break; + case FCVTNU_xs: + WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven)); + break; + case FCVTNU_wd: + WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven)); + break; + case FCVTNU_xd: + WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven)); + break; + case FCVTZS_wh: + WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero)); + break; + case FCVTZS_xh: + WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero)); + break; + case FCVTZS_ws: + WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero)); + break; + case FCVTZS_xs: + WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero)); + break; + case FCVTZS_wd: + WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero)); + break; + case FCVTZS_xd: + WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero)); + break; + case FCVTZU_wh: + WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero)); + break; + case FCVTZU_xh: + WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero)); + break; + case FCVTZU_ws: + WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero)); + break; + case FCVTZU_xs: + WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero)); + break; + case FCVTZU_wd: + WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero)); + break; + case FCVTZU_xd: + WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero)); + break; + case FJCVTZS: + WriteWRegister(dst, FPToFixedJS(ReadDRegister(src))); + break; + case FMOV_hw: + WriteHRegister(dst, ReadWRegister(src) & kHRegMask); + break; + case FMOV_wh: + WriteWRegister(dst, ReadHRegisterBits(src)); + break; + case FMOV_xh: + WriteXRegister(dst, ReadHRegisterBits(src)); + break; + case FMOV_hx: + WriteHRegister(dst, ReadXRegister(src) & kHRegMask); + break; + case FMOV_ws: + WriteWRegister(dst, ReadSRegisterBits(src)); + break; + case FMOV_xd: + WriteXRegister(dst, ReadDRegisterBits(src)); + break; + case FMOV_sw: + WriteSRegisterBits(dst, ReadWRegister(src)); + break; + case FMOV_dx: + WriteDRegisterBits(dst, ReadXRegister(src)); + break; + case FMOV_d1_x: + // Zero bits beyond the MSB of a Q register. + mov(kFormat16B, ReadVRegister(dst), ReadVRegister(dst)); + LogicVRegister(ReadVRegister(dst)) + .SetUint(kFormatD, 1, ReadXRegister(src)); + break; + case FMOV_x_d1: + WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1)); + break; + + // A 32-bit input can be handled in the same way as a 64-bit input, since + // the sign- or zero-extension will not affect the conversion. + case SCVTF_dx: + WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round)); + break; + case SCVTF_dw: + WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round)); + break; + case UCVTF_dx: + WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round)); + break; + case UCVTF_dw: { + WriteDRegister(dst, + UFixedToDouble(ReadRegister(src), 0, round)); + break; + } + case SCVTF_sx: + WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round)); + break; + case SCVTF_sw: + WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round)); + break; + case UCVTF_sx: + WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round)); + break; + case UCVTF_sw: { + WriteSRegister(dst, UFixedToFloat(ReadRegister(src), 0, round)); + break; + } + case SCVTF_hx: + WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round)); + break; + case SCVTF_hw: + WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round)); + break; + case UCVTF_hx: + WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round)); + break; + case UCVTF_hw: { + WriteHRegister(dst, + UFixedToFloat16(ReadRegister(src), 0, round)); + break; + } + + default: + VIXL_UNREACHABLE(); + } +} + + +void Simulator::VisitFPFixedPointConvert(const Instruction* instr) { + AssertSupportedFPCR(); + + unsigned dst = instr->GetRd(); + unsigned src = instr->GetRn(); + int fbits = 64 - instr->GetFPScale(); + + FPRounding round = ReadRMode(); + + switch (instr->Mask(FPFixedPointConvertMask)) { + // A 32-bit input can be handled in the same way as a 64-bit input, since + // the sign- or zero-extension will not affect the conversion. + case SCVTF_dx_fixed: + WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round)); + break; + case SCVTF_dw_fixed: + WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round)); + break; + case UCVTF_dx_fixed: + WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round)); + break; + case UCVTF_dw_fixed: { + WriteDRegister(dst, + UFixedToDouble(ReadRegister(src), fbits, round)); + break; + } + case SCVTF_sx_fixed: + WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round)); + break; + case SCVTF_sw_fixed: + WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round)); + break; + case UCVTF_sx_fixed: + WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round)); + break; + case UCVTF_sw_fixed: { + WriteSRegister(dst, + UFixedToFloat(ReadRegister(src), fbits, round)); + break; + } + case SCVTF_hx_fixed: + WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round)); + break; + case SCVTF_hw_fixed: + WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round)); + break; + case UCVTF_hx_fixed: + WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round)); + break; + case UCVTF_hw_fixed: { + WriteHRegister(dst, + UFixedToFloat16(ReadRegister(src), + fbits, + round)); + break; + } + case FCVTZS_xd_fixed: + WriteXRegister(dst, + FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits), + FPZero)); + break; + case FCVTZS_wd_fixed: + WriteWRegister(dst, + FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits), + FPZero)); + break; + case FCVTZU_xd_fixed: + WriteXRegister(dst, + FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits), + FPZero)); + break; + case FCVTZU_wd_fixed: + WriteWRegister(dst, + FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits), + FPZero)); + break; + case FCVTZS_xs_fixed: + WriteXRegister(dst, + FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits), + FPZero)); + break; + case FCVTZS_ws_fixed: + WriteWRegister(dst, + FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits), + FPZero)); + break; + case FCVTZU_xs_fixed: + WriteXRegister(dst, + FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits), + FPZero)); + break; + case FCVTZU_ws_fixed: + WriteWRegister(dst, + FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits), + FPZero)); + break; + case FCVTZS_xh_fixed: { + double output = + static_cast(ReadHRegister(src)) * std::pow(2.0, fbits); + WriteXRegister(dst, FPToInt64(output, FPZero)); + break; + } + case FCVTZS_wh_fixed: { + double output = + static_cast(ReadHRegister(src)) * std::pow(2.0, fbits); + WriteWRegister(dst, FPToInt32(output, FPZero)); + break; + } + case FCVTZU_xh_fixed: { + double output = + static_cast(ReadHRegister(src)) * std::pow(2.0, fbits); + WriteXRegister(dst, FPToUInt64(output, FPZero)); + break; + } + case FCVTZU_wh_fixed: { + double output = + static_cast(ReadHRegister(src)) * std::pow(2.0, fbits); + WriteWRegister(dst, FPToUInt32(output, FPZero)); + break; + } + default: + VIXL_UNREACHABLE(); + } +} + + +void Simulator::VisitFPCompare(const Instruction* instr) { + AssertSupportedFPCR(); + + FPTrapFlags trap = DisableTrap; + switch (instr->Mask(FPCompareMask)) { + case FCMPE_h: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_h: + FPCompare(ReadHRegister(instr->GetRn()), + ReadHRegister(instr->GetRm()), + trap); + break; + case FCMPE_s: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_s: + FPCompare(ReadSRegister(instr->GetRn()), + ReadSRegister(instr->GetRm()), + trap); + break; + case FCMPE_d: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_d: + FPCompare(ReadDRegister(instr->GetRn()), + ReadDRegister(instr->GetRm()), + trap); + break; + case FCMPE_h_zero: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_h_zero: + FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap); + break; + case FCMPE_s_zero: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_s_zero: + FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap); + break; + case FCMPE_d_zero: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCMP_d_zero: + FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitFPConditionalCompare(const Instruction* instr) { + AssertSupportedFPCR(); + + FPTrapFlags trap = DisableTrap; + switch (instr->Mask(FPConditionalCompareMask)) { + case FCCMPE_h: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCCMP_h: + if (ConditionPassed(instr->GetCondition())) { + FPCompare(ReadHRegister(instr->GetRn()), + ReadHRegister(instr->GetRm()), + trap); + } else { + ReadNzcv().SetFlags(instr->GetNzcv()); + LogSystemRegister(NZCV); + } + break; + case FCCMPE_s: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCCMP_s: + if (ConditionPassed(instr->GetCondition())) { + FPCompare(ReadSRegister(instr->GetRn()), + ReadSRegister(instr->GetRm()), + trap); + } else { + ReadNzcv().SetFlags(instr->GetNzcv()); + LogSystemRegister(NZCV); + } + break; + case FCCMPE_d: + trap = EnableTrap; + VIXL_FALLTHROUGH(); + case FCCMP_d: + if (ConditionPassed(instr->GetCondition())) { + FPCompare(ReadDRegister(instr->GetRn()), + ReadDRegister(instr->GetRm()), + trap); + } else { + ReadNzcv().SetFlags(instr->GetNzcv()); + LogSystemRegister(NZCV); + } + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitFPConditionalSelect(const Instruction* instr) { + AssertSupportedFPCR(); + + Instr selected; + if (ConditionPassed(instr->GetCondition())) { + selected = instr->GetRn(); + } else { + selected = instr->GetRm(); + } + + switch (instr->Mask(FPConditionalSelectMask)) { + case FCSEL_h: + WriteHRegister(instr->GetRd(), ReadHRegister(selected)); + break; + case FCSEL_s: + WriteSRegister(instr->GetRd(), ReadSRegister(selected)); + break; + case FCSEL_d: + WriteDRegister(instr->GetRd(), ReadDRegister(selected)); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateFPRoundIntToSize(const Instruction* instr) { + AssertSupportedFPCR(); + + struct FPRoundInfo { + VectorFormat vform; + bool use_fpcr; + FrintMode frint_mode; + }; + + std::unordered_map modes = { + {"frint32x_d_floatdp1"_h, {kFormatD, true, kFrintToInt32}}, + {"frint32x_s_floatdp1"_h, {kFormatS, true, kFrintToInt32}}, + {"frint64x_d_floatdp1"_h, {kFormatD, true, kFrintToInt64}}, + {"frint64x_s_floatdp1"_h, {kFormatS, true, kFrintToInt64}}, + {"frint32z_d_floatdp1"_h, {kFormatD, false, kFrintToInt32}}, + {"frint32z_s_floatdp1"_h, {kFormatS, false, kFrintToInt32}}, + {"frint64z_d_floatdp1"_h, {kFormatD, false, kFrintToInt64}}, + {"frint64z_s_floatdp1"_h, {kFormatS, false, kFrintToInt64}}, + }; + VIXL_ASSERT(modes.count(form_hash_) == 1); + + auto [vform, use_fpcr, frint_mode] = modes[form_hash_]; + FPRounding rounding_mode = + use_fpcr ? static_cast(ReadFpcr().GetRMode()) : FPZero; + bool inexact_exception = true; + + unsigned fd = instr->GetRd(); + SimVRegister& rd = ReadVRegister(fd); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + frint(vform, rd, rn, rounding_mode, inexact_exception, frint_mode); + // Explicitly log the register update whilst we have type information. + LogVRegister(fd, GetPrintRegisterFormatFP(vform)); +} + +void Simulator::SimulateFPRoundInt(const Instruction* instr) { + AssertSupportedFPCR(); + + struct FPRoundInfo { + VectorFormat vform; + bool use_fpcr; + FPRounding rounding_mode; + bool inexact_exception; + }; + + std::unordered_map modes = + {{"frinta_d_floatdp1"_h, {kFormatD, false, FPTieAway, false}}, + {"frinta_h_floatdp1"_h, {kFormatH, false, FPTieAway, false}}, + {"frinta_s_floatdp1"_h, {kFormatS, false, FPTieAway, false}}, + {"frinti_d_floatdp1"_h, {kFormatD, true, FPZero, false}}, + {"frinti_h_floatdp1"_h, {kFormatH, true, FPZero, false}}, + {"frinti_s_floatdp1"_h, {kFormatS, true, FPZero, false}}, + {"frintm_d_floatdp1"_h, {kFormatD, false, FPNegativeInfinity, false}}, + {"frintm_h_floatdp1"_h, {kFormatH, false, FPNegativeInfinity, false}}, + {"frintm_s_floatdp1"_h, {kFormatS, false, FPNegativeInfinity, false}}, + {"frintn_d_floatdp1"_h, {kFormatD, false, FPTieEven, false}}, + {"frintn_h_floatdp1"_h, {kFormatH, false, FPTieEven, false}}, + {"frintn_s_floatdp1"_h, {kFormatS, false, FPTieEven, false}}, + {"frintp_d_floatdp1"_h, {kFormatD, false, FPPositiveInfinity, false}}, + {"frintp_h_floatdp1"_h, {kFormatH, false, FPPositiveInfinity, false}}, + {"frintp_s_floatdp1"_h, {kFormatS, false, FPPositiveInfinity, false}}, + {"frintx_d_floatdp1"_h, {kFormatD, true, FPZero, true}}, + {"frintx_h_floatdp1"_h, {kFormatH, true, FPZero, true}}, + {"frintx_s_floatdp1"_h, {kFormatS, true, FPZero, true}}, + {"frintz_d_floatdp1"_h, {kFormatD, false, FPZero, false}}, + {"frintz_h_floatdp1"_h, {kFormatH, false, FPZero, false}}, + {"frintz_s_floatdp1"_h, {kFormatS, false, FPZero, false}}}; + VIXL_ASSERT(modes.count(form_hash_) == 1); + + auto [vform, use_fpcr, rounding_mode, inexact_exception] = modes[form_hash_]; + + rounding_mode = + use_fpcr ? static_cast(ReadFpcr().GetRMode()) : rounding_mode; + + unsigned fd = instr->GetRd(); + SimVRegister& rd = ReadVRegister(fd); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + frint(vform, rd, rn, rounding_mode, inexact_exception); + // Explicitly log the register update whilst we have type information. + LogVRegister(fd, GetPrintRegisterFormatFP(vform)); +} + +void Simulator::SimulateFPConvert(const Instruction* instr) { + AssertSupportedFPCR(); + unsigned fd = instr->GetRd(); + unsigned fn = instr->GetRn(); + UseDefaultNaN nan = ReadDN(); + + Float16 hn = ReadHRegister(fn); + float sn = ReadSRegister(fn); + double dn = ReadDRegister(fn); + + switch (form_hash_) { + case "fmov_h_floatdp1"_h: + WriteHRegister(fd, hn); + break; + case "fmov_s_floatdp1"_h: + WriteSRegister(fd, sn); + break; + case "fmov_d_floatdp1"_h: + WriteDRegister(fd, dn); + break; + case "fcvt_ds_floatdp1"_h: + WriteDRegister(fd, FPToDouble(sn, nan)); + break; + case "fcvt_sd_floatdp1"_h: + WriteSRegister(fd, FPToFloat(dn, FPTieEven, nan)); + break; + case "fcvt_hs_floatdp1"_h: + WriteHRegister(fd, Float16ToRawbits(FPToFloat16(sn, FPTieEven, nan))); + break; + case "fcvt_sh_floatdp1"_h: + WriteSRegister(fd, FPToFloat(hn, nan)); + break; + case "fcvt_dh_floatdp1"_h: + WriteDRegister(fd, FPToDouble(hn, nan)); + break; + case "fcvt_hd_floatdp1"_h: + WriteHRegister(fd, Float16ToRawbits(FPToFloat16(dn, FPTieEven, nan))); + break; + case "bfcvt_bs_floatdp1"_h: + WriteHRegister(fd, BFloat16ToRawbits(FPToBFloat16(sn, FPTieEven, nan))); + break; + } +} + +void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) { + AssertSupportedFPCR(); + + VectorFormat vform = kFormatD; + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "fabs_d_floatdp1"_h: + fabs_(vform = kFormatD, rd, rn); + break; + case "fabs_h_floatdp1"_h: + fabs_(vform = kFormatH, rd, rn); + break; + case "fabs_s_floatdp1"_h: + fabs_(vform = kFormatS, rd, rn); + break; + case "fneg_d_floatdp1"_h: + fneg(vform = kFormatD, rd, rn); + break; + case "fneg_h_floatdp1"_h: + fneg(vform = kFormatH, rd, rn); + break; + case "fneg_s_floatdp1"_h: + fneg(vform = kFormatS, rd, rn); + break; + case "fsqrt_d_floatdp1"_h: + fsqrt(vform = kFormatD, rd, rn); + break; + case "fsqrt_h_floatdp1"_h: + fsqrt(vform = kFormatH, rd, rn); + break; + case "fsqrt_s_floatdp1"_h: + fsqrt(vform = kFormatS, rd, rn); + break; + } + // Explicitly log the register update whilst we have type information. + LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform)); +} + + +void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) { + AssertSupportedFPCR(); + + VectorFormat vform; + switch (instr->Mask(FPTypeMask)) { + default: + VIXL_UNREACHABLE_OR_FALLTHROUGH(); + case FP64: + vform = kFormatD; + break; + case FP32: + vform = kFormatS; + break; + case FP16: + vform = kFormatH; + break; + } + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(FPDataProcessing2SourceMask)) { + case FADD_h: + case FADD_s: + case FADD_d: + fadd(vform, rd, rn, rm); + break; + case FSUB_h: + case FSUB_s: + case FSUB_d: + fsub(vform, rd, rn, rm); + break; + case FMUL_h: + case FMUL_s: + case FMUL_d: + fmul(vform, rd, rn, rm); + break; + case FNMUL_h: + case FNMUL_s: + case FNMUL_d: + fnmul(vform, rd, rn, rm); + break; + case FDIV_h: + case FDIV_s: + case FDIV_d: + fdiv(vform, rd, rn, rm); + break; + case FMAX_h: + case FMAX_s: + case FMAX_d: + fmax(vform, rd, rn, rm); + break; + case FMIN_h: + case FMIN_s: + case FMIN_d: + fmin(vform, rd, rn, rm); + break; + case FMAXNM_h: + case FMAXNM_s: + case FMAXNM_d: + fmaxnm(vform, rd, rn, rm); + break; + case FMINNM_h: + case FMINNM_s: + case FMINNM_d: + fminnm(vform, rd, rn, rm); + break; + default: + VIXL_UNREACHABLE(); + } + // Explicitly log the register update whilst we have type information. + LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform)); +} + + +void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) { + AssertSupportedFPCR(); + + unsigned fd = instr->GetRd(); + unsigned fn = instr->GetRn(); + unsigned fm = instr->GetRm(); + unsigned fa = instr->GetRa(); + + switch (instr->Mask(FPDataProcessing3SourceMask)) { + // fd = fa +/- (fn * fm) + case FMADD_h: + WriteHRegister(fd, + FPMulAdd(ReadHRegister(fa), + ReadHRegister(fn), + ReadHRegister(fm))); + break; + case FMSUB_h: + WriteHRegister(fd, + FPMulAdd(ReadHRegister(fa), + -ReadHRegister(fn), + ReadHRegister(fm))); + break; + case FMADD_s: + WriteSRegister(fd, + FPMulAdd(ReadSRegister(fa), + ReadSRegister(fn), + ReadSRegister(fm))); + break; + case FMSUB_s: + WriteSRegister(fd, + FPMulAdd(ReadSRegister(fa), + -ReadSRegister(fn), + ReadSRegister(fm))); + break; + case FMADD_d: + WriteDRegister(fd, + FPMulAdd(ReadDRegister(fa), + ReadDRegister(fn), + ReadDRegister(fm))); + break; + case FMSUB_d: + WriteDRegister(fd, + FPMulAdd(ReadDRegister(fa), + -ReadDRegister(fn), + ReadDRegister(fm))); + break; + // Negated variants of the above. + case FNMADD_h: + WriteHRegister(fd, + FPMulAdd(-ReadHRegister(fa), + -ReadHRegister(fn), + ReadHRegister(fm))); + break; + case FNMSUB_h: + WriteHRegister(fd, + FPMulAdd(-ReadHRegister(fa), + ReadHRegister(fn), + ReadHRegister(fm))); + break; + case FNMADD_s: + WriteSRegister(fd, + FPMulAdd(-ReadSRegister(fa), + -ReadSRegister(fn), + ReadSRegister(fm))); + break; + case FNMSUB_s: + WriteSRegister(fd, + FPMulAdd(-ReadSRegister(fa), + ReadSRegister(fn), + ReadSRegister(fm))); + break; + case FNMADD_d: + WriteDRegister(fd, + FPMulAdd(-ReadDRegister(fa), + -ReadDRegister(fn), + ReadDRegister(fm))); + break; + case FNMSUB_d: + WriteDRegister(fd, + FPMulAdd(-ReadDRegister(fa), + ReadDRegister(fn), + ReadDRegister(fm))); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +bool Simulator::FPProcessNaNs(const Instruction* instr) { + unsigned fd = instr->GetRd(); + unsigned fn = instr->GetRn(); + unsigned fm = instr->GetRm(); + bool done = false; + + if (instr->Mask(FP64) == FP64) { + double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm)); + if (IsNaN(result)) { + WriteDRegister(fd, result); + done = true; + } + } else if (instr->Mask(FP32) == FP32) { + float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm)); + if (IsNaN(result)) { + WriteSRegister(fd, result); + done = true; + } + } else { + VIXL_ASSERT(instr->Mask(FP16) == FP16); + VIXL_UNIMPLEMENTED(); + } + + return done; +} + + +bool Simulator::SysOp_W(int op, int64_t val) { + switch (op) { + case IVAU: + case CVAC: + case CVAU: + case CVAP: + case CVADP: + case CIVAC: + case CGVAC: + case CGDVAC: + case CGVAP: + case CGDVAP: + case CIGVAC: + case CIGDVAC: { + // Perform a placeholder memory access to ensure that we have read access + // to the specified address. The read access does not require a tag match, + // so temporarily disable MTE. + bool mte_enabled = MetaDataDepot::MetaDataMTE::IsActive(); + MetaDataDepot::MetaDataMTE::SetActive(false); + volatile uint8_t y = *MemRead(val); + MetaDataDepot::MetaDataMTE::SetActive(mte_enabled); + USE(y); + break; + } + case ZVA: { + if ((dczid_ & 0x10) != 0) { // Check dc zva is enabled. + return false; + } + int blocksize = (1 << (dczid_ & 0xf)) * kWRegSizeInBytes; + VIXL_ASSERT(IsMultiple(blocksize, sizeof(uint64_t))); + uintptr_t addr = AlignDown(val, blocksize); + for (int i = 0; i < blocksize; i += sizeof(uint64_t)) { + MemWrite(addr + i, 0); + LogWriteU64(0, addr + i); + } + break; + } + // TODO: Implement GVA, GZVA. + default: + VIXL_UNIMPLEMENTED(); + return false; + } + return true; +} + +void Simulator::PACHelper(int dst, + int src, + PACKey key, + decltype(&Simulator::AddPAC) pac_fn) { + VIXL_ASSERT((dst == 17) || (dst == 30)); + VIXL_ASSERT((src == -1) || (src == 16) || (src == 31)); + + uint64_t modifier = (src == -1) ? 0 : ReadXRegister(src, Reg31IsStackPointer); + uint64_t result = + (this->*pac_fn)(ReadXRegister(dst), modifier, key, kInstructionPointer); + WriteXRegister(dst, result); +} + +void Simulator::VisitSystem(const Instruction* instr) { + PACKey pac_key = kPACKeyIA; // Default key for PAC/AUTH handling. + + switch (form_hash_) { + case "cfinv_m_pstate"_h: + ReadNzcv().SetC(!ReadC()); + LogSystemRegister(NZCV); + break; + case "axflag_m_pstate"_h: + ReadNzcv().SetN(0); + ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV()); + ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV()); + ReadNzcv().SetV(0); + LogSystemRegister(NZCV); + break; + case "xaflag_m_pstate"_h: { + // Can't set the flags in place due to the logical dependencies. + uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1; + uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC(); + uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ(); + uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ(); + ReadNzcv().SetN(n); + ReadNzcv().SetZ(z); + ReadNzcv().SetC(c); + ReadNzcv().SetV(v); + LogSystemRegister(NZCV); + break; + } + case "xpaclri_hi_hints"_h: + WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer)); + break; + case "clrex_bn_barriers"_h: + PrintExclusiveAccessWarning(); + ClearLocalMonitor(); + break; + case "msr_sr_systemmove"_h: + switch (instr->GetImmSystemRegister()) { + case NZCV: + ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt())); + LogSystemRegister(NZCV); + break; + case FPCR: + ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt())); + LogSystemRegister(FPCR); + break; + default: + VIXL_UNIMPLEMENTED(); + } + break; + case "mrs_rs_systemmove"_h: + switch (instr->GetImmSystemRegister()) { + case NZCV: + WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue()); + break; + case FPCR: + WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue()); + break; + case RNDR: + case RNDRRS: { + uint64_t high = rand_gen_(); + uint64_t low = rand_gen_(); + uint64_t rand_num = (high << 32) | (low & 0xffffffff); + WriteXRegister(instr->GetRt(), rand_num); + // Simulate successful random number generation. + // TODO: Return failure occasionally as a random number cannot be + // returned in a period of time. + ReadNzcv().SetRawValue(NoFlag); + LogSystemRegister(NZCV); + break; + } + case DCZID_EL0: + WriteXRegister(instr->GetRt(), dczid_); + break; + default: + VIXL_UNIMPLEMENTED(); + } + break; + case "chkfeat_hf_hints"_h: { + uint64_t feat_select = ReadXRegister(16); + uint64_t gcs_enabled = IsGCSCheckEnabled() ? 1 : 0; + feat_select &= ~gcs_enabled; + WriteXRegister(16, feat_select); + break; + } + case "hint_hm_hints"_h: + case "nop_hi_hints"_h: + case "yield_hi_hints"_h: + case "esb_hi_hints"_h: + case "csdb_hi_hints"_h: + break; + case "bti_hb_hints"_h: + switch (instr->GetImmHint()) { + case BTI_jc: + break; + case BTI: + if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) { + VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType."); + } + break; + case BTI_c: + if (PcIsInGuardedPage() && + (ReadBType() == BranchFromGuardedNotToIP)) { + VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType."); + } + break; + case BTI_j: + if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) { + VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType."); + } + break; + default: + VIXL_UNREACHABLE(); + } + return; + case "pacib1716_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "pacia1716_hi_hints"_h: + PACHelper(17, 16, pac_key, &Simulator::AddPAC); + break; + case "pacibsp_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "paciasp_hi_hints"_h: + PACHelper(30, 31, pac_key, &Simulator::AddPAC); + + // Check BType allows PACI[AB]SP instructions. + if (PcIsInGuardedPage()) { + switch (ReadBType()) { + case BranchFromGuardedNotToIP: + // TODO: This case depends on the value of SCTLR_EL1.BT0, which we + // assume here to be zero. This allows execution of PACI[AB]SP when + // BTYPE is BranchFromGuardedNotToIP (0b11). + case DefaultBType: + case BranchFromUnguardedOrToIP: + case BranchAndLink: + break; + } + } + break; + case "pacibz_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "paciaz_hi_hints"_h: + PACHelper(30, -1, pac_key, &Simulator::AddPAC); + break; + case "autib1716_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "autia1716_hi_hints"_h: + PACHelper(17, 16, pac_key, &Simulator::AuthPAC); + break; + case "autibsp_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "autiasp_hi_hints"_h: + PACHelper(30, 31, pac_key, &Simulator::AuthPAC); + break; + case "autibz_hi_hints"_h: + pac_key = kPACKeyIB; + VIXL_FALLTHROUGH(); + case "autiaz_hi_hints"_h: + PACHelper(30, -1, pac_key, &Simulator::AuthPAC); + break; + case "dsb_bo_barriers"_h: + case "dmb_bo_barriers"_h: + case "isb_bi_barriers"_h: + VIXL_SYNC(); + break; + case "sys_cr_systeminstrs"_h: { + uint64_t rt = ReadXRegister(instr->GetRt()); + uint32_t sysop = instr->GetSysOp(); + if (sysop == GCSSS1) { + uint64_t incoming_size = rt >> 32; + // Drop upper 32 bits to get GCS index. + uint64_t incoming_gcs = rt & 0xffffffff; + GuardedControlStack outgoing_gcs = ActivateGCS(incoming_gcs); + uint64_t incoming_seal = GCSPop(); + if (((incoming_seal ^ rt) != 1) || + (GetGCSStorage()->size() != incoming_size)) { + char msg[128]; + snprintf(msg, + sizeof(msg), + "GCS: invalid incoming stack: 0x%016" PRIx64 "\n", + incoming_seal); + ReportGCSFailure(msg); + } + GCSPush(outgoing_gcs.token + 5); + } else if (sysop == GCSPUSHM) { + GCSPush(ReadXRegister(instr->GetRt())); + } else { + if (!SysOp_W(sysop, rt)) { + VisitUnallocated(instr); + } + } + break; + } + case "sysl_rc_systeminstrs"_h: { + uint32_t sysop = instr->GetSysOp(); + if (sysop == GCSPOPM) { + uint64_t addr = GCSPop(); + WriteXRegister(instr->GetRt(), addr); + } else if (sysop == GCSSS2) { + uint64_t outgoing_gcs = GCSPop(); + // Check for token inserted by gcsss1. + if ((outgoing_gcs & 7) != 5) { + char msg[128]; + snprintf(msg, + sizeof(msg), + "GCS: outgoing stack has no token: 0x%016" PRIx64 "\n", + outgoing_gcs); + ReportGCSFailure(msg); + } + outgoing_gcs &= ~UINT64_C(0x3ff); + GuardedControlStack incoming_gcs = ActivateGCS(outgoing_gcs); + + // Encode the size into the outgoing stack seal, to check later. + uint64_t size = GetGCSStorage()->size(); + VIXL_ASSERT(IsUint32(size)); + VIXL_ASSERT(IsUint32(outgoing_gcs + 1)); + uint64_t outgoing_seal = (size << 32) | (outgoing_gcs + 1); + GCSPush(outgoing_seal); + ActivateGCS(incoming_gcs); + WriteXRegister(instr->GetRt(), outgoing_seal - 1); + } else { + VIXL_UNIMPLEMENTED(); + } + break; + } + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitException(const Instruction* instr) { + switch (instr->Mask(ExceptionMask)) { + case HLT: + switch (instr->GetImmException()) { + case kUnreachableOpcode: + DoUnreachable(instr); + return; + case kTraceOpcode: + DoTrace(instr); + return; + case kLogOpcode: + DoLog(instr); + return; + case kPrintfOpcode: + DoPrintf(instr); + return; + case kRuntimeCallOpcode: + DoRuntimeCall(instr); + return; + case kSetCPUFeaturesOpcode: + case kEnableCPUFeaturesOpcode: + case kDisableCPUFeaturesOpcode: + DoConfigureCPUFeatures(instr); + return; + case kSaveCPUFeaturesOpcode: + DoSaveCPUFeatures(instr); + return; + case kRestoreCPUFeaturesOpcode: + DoRestoreCPUFeatures(instr); + return; + case kMTEActive: + MetaDataDepot::MetaDataMTE::SetActive(true); + return; + case kMTEInactive: + MetaDataDepot::MetaDataMTE::SetActive(false); + return; + default: + HostBreakpoint(); + return; + } + case BRK: + if (debugger_enabled_) { + uint64_t next_instr = + reinterpret_cast(pc_->GetNextInstruction()); + if (!debugger_->IsBreakpoint(next_instr)) { + debugger_->RegisterBreakpoint(next_instr); + } + } else { + HostBreakpoint(); + } + return; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitCrypto2RegSHA(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "sha1h_ss_cryptosha2"_h: + ror(kFormatS, rd, rn, 2); + break; + case "sha1su1_vv_cryptosha2"_h: { + SimVRegister temp; + + // temp = srcdst ^ (src >> 32); + ext(kFormat16B, temp, rn, temp, 4); + eor(kFormat16B, temp, rd, temp); + + // srcdst = ROL(temp, 1) ^ (ROL(temp, 2) << 96) + rol(kFormat4S, rd, temp, 1); + rol(kFormatS, temp, temp, 2); // kFormatS will zero bits <127:32> + ext(kFormat16B, temp, temp, temp, 4); + eor(kFormat16B, rd, rd, temp); + break; + } + case "sha256su0_vv_cryptosha2"_h: + sha2su0(rd, rn); + break; + } +} + + +void Simulator::VisitCrypto3RegSHA(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (form_hash_) { + case "sha1c_qsv_cryptosha3"_h: + sha1<"choose"_h>(rd, rn, rm); + break; + case "sha1m_qsv_cryptosha3"_h: + sha1<"majority"_h>(rd, rn, rm); + break; + case "sha1p_qsv_cryptosha3"_h: + sha1<"parity"_h>(rd, rn, rm); + break; + case "sha1su0_vvv_cryptosha3"_h: { + SimVRegister temp; + ext(kFormat16B, temp, rd, rn, 8); + eor(kFormat16B, temp, temp, rd); + eor(kFormat16B, rd, temp, rm); + break; + } + case "sha256h_qqv_cryptosha3"_h: + sha2h(rd, rn, rm, /* part1 = */ true); + break; + case "sha256h2_qqv_cryptosha3"_h: + sha2h(rd, rn, rm, /* part1 = */ false); + break; + case "sha256su1_vvv_cryptosha3"_h: + sha2su1(rd, rn, rm); + break; + } +} + + +void Simulator::VisitCryptoAES(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister temp; + + switch (form_hash_) { + case "aesd_b_cryptoaes"_h: + eor(kFormat16B, temp, rd, rn); + aes(rd, temp, /* decrypt = */ true); + break; + case "aese_b_cryptoaes"_h: + eor(kFormat16B, temp, rd, rn); + aes(rd, temp, /* decrypt = */ false); + break; + case "aesimc_b_cryptoaes"_h: + aesmix(rd, rn, /* inverse = */ true); + break; + case "aesmc_b_cryptoaes"_h: + aesmix(rd, rn, /* inverse = */ false); + break; + } +} + +void Simulator::VisitCryptoSM3(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + SimVRegister& ra = ReadVRegister(instr->GetRa()); + int index = instr->ExtractBits(13, 12); + + bool is_a = false; + switch (form_hash_) { + case "sm3partw1_vvv4_cryptosha512_3"_h: + sm3partw1(rd, rn, rm); + break; + case "sm3partw2_vvv4_cryptosha512_3"_h: + sm3partw2(rd, rn, rm); + break; + case "sm3ss1_vvv4_crypto4"_h: + sm3ss1(rd, rn, rm, ra); + break; + case "sm3tt1a_vvv4_crypto3_imm2"_h: + is_a = true; + VIXL_FALLTHROUGH(); + case "sm3tt1b_vvv4_crypto3_imm2"_h: + sm3tt1(rd, rn, rm, index, is_a); + break; + case "sm3tt2a_vvv4_crypto3_imm2"_h: + is_a = true; + VIXL_FALLTHROUGH(); + case "sm3tt2b_vvv_crypto3_imm2"_h: + sm3tt2(rd, rn, rm, index, is_a); + break; + } +} + +void Simulator::VisitCryptoSM4(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + bool is_key = false; + switch (form_hash_) { + case "sm4ekey_vvv4_cryptosha512_3"_h: + is_key = true; + VIXL_FALLTHROUGH(); + case "sm4e_vv4_cryptosha512_2"_h: + sm4(rd, rn, rm, is_key); + break; + } +} + +void Simulator::SimulateSHA512(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (form_hash_) { + case "sha512h_qqv_cryptosha512_3"_h: + sha512h(rd, rn, rm); + break; + case "sha512h2_qqv_cryptosha512_3"_h: + sha512h2(rd, rn, rm); + break; + case "sha512su0_vv2_cryptosha512_2"_h: + sha512su0(rd, rn); + break; + case "sha512su1_vvv2_cryptosha512_3"_h: + sha512su1(rd, rn, rm); + break; + } +} + +void Simulator::SimulateNEONRoundIntToSize(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vform = nfd.GetVectorFormat(nfd.FPFormatMap()); + FPRounding rounding_mode = static_cast(ReadFpcr().GetRMode()); + FrintMode frint_mode = kFrintToInt32; + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + frint_mode = kFrintToInt32; + switch (form_hash_) { + case "frint32z_asimdmisc_r"_h: + rounding_mode = FPZero; + break; + case "frint64z_asimdmisc_r"_h: + rounding_mode = FPZero; + VIXL_FALLTHROUGH(); + case "frint64x_asimdmisc_r"_h: + frint_mode = kFrintToInt64; + break; + } + frint(vform, + rd, + rn, + rounding_mode, + /* inexact_exception = */ true, + frint_mode); +} + +void Simulator::SimulateNEONRoundInt(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vform = nfd.GetVectorFormat(nfd.FPFormatMap()); + FPRounding rounding_mode = static_cast(ReadFpcr().GetRMode()); + bool inexact_exception = false; + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "frinta_asimdmisc_r"_h: + rounding_mode = FPTieAway; + break; + case "frintm_asimdmisc_r"_h: + rounding_mode = FPNegativeInfinity; + break; + case "frintn_asimdmisc_r"_h: + rounding_mode = FPTieEven; + break; + case "frintp_asimdmisc_r"_h: + rounding_mode = FPPositiveInfinity; + break; + case "frintx_asimdmisc_r"_h: + inexact_exception = true; + break; + case "frintz_asimdmisc_r"_h: + rounding_mode = FPZero; + break; + case "frinti_asimdmisc_r"_h: + // Uses FPCR - nothing to do. + break; + } + frint(vform, rd, rn, rounding_mode, inexact_exception); +} + +void Simulator::SimulateNEONFPConvert(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vform = nfd.GetVectorFormat(nfd.FPFormatMap()); + static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}}; + VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl); + + static const NEONFormatMap map_fcvtn = {{22, 30}, + {NF_4H, NF_8H, NF_2S, NF_4S}}; + VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + bool is_q = instr->Mask(NEON_Q) != 0; + std::function + handler = nullptr; + + switch (form_hash_) { + case "fcvtas_asimdmisc_r"_h: + fcvts(vform, rd, rn, FPTieAway); + break; + case "fcvtau_asimdmisc_r"_h: + fcvtu(vform, rd, rn, FPTieAway); + break; + case "fcvtms_asimdmisc_r"_h: + fcvts(vform, rd, rn, FPNegativeInfinity); + break; + case "fcvtmu_asimdmisc_r"_h: + fcvtu(vform, rd, rn, FPNegativeInfinity); + break; + case "fcvtns_asimdmisc_r"_h: + fcvts(vform, rd, rn, FPTieEven); + break; + case "fcvtnu_asimdmisc_r"_h: + fcvtu(vform, rd, rn, FPTieEven); + break; + case "fcvtps_asimdmisc_r"_h: + fcvts(vform, rd, rn, FPPositiveInfinity); + break; + case "fcvtpu_asimdmisc_r"_h: + fcvtu(vform, rd, rn, FPPositiveInfinity); + break; + case "fcvtzs_asimdmisc_r"_h: + fcvts(vform, rd, rn, FPZero); + break; + case "fcvtzu_asimdmisc_r"_h: + fcvtu(vform, rd, rn, FPZero); + break; + case "fcvtl_asimdmisc_l"_h: + handler = is_q ? &Simulator::fcvtl2 : &Simulator::fcvtl; + handler(this, vf_fcvtl, rd, rn); + break; + case "fcvtn_asimdmisc_n"_h: + handler = is_q ? &Simulator::fcvtn2 : &Simulator::fcvtn; + handler(this, vf_fcvtn, rd, rn); + break; + case "fcvtxn_asimdmisc_n"_h: + handler = is_q ? &Simulator::fcvtxn2 : &Simulator::fcvtxn; + handler(this, vf_fcvtn, rd, rn); + break; + case "bfcvtn_asimdmisc_4s"_h: + handler = is_q ? &Simulator::bfcvtn2 : &Simulator::bfcvtn; + handler(this, is_q ? kFormat8H : kFormat4H, rd, rn); + break; + } +} + +void Simulator::SimulateNEONFP2RegMisc(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vform = nfd.GetVectorFormat(nfd.FPFormatMap()); + FPRounding rounding_mode = static_cast(ReadFpcr().GetRMode()); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (form_hash_) { + case "fabs_asimdmisc_r"_h: + fabs_(vform, rd, rn); + break; + case "fneg_asimdmisc_r"_h: + fneg(vform, rd, rn); + break; + case "fsqrt_asimdmisc_r"_h: + fsqrt(vform, rd, rn); + break; + case "scvtf_asimdmisc_r"_h: + scvtf(vform, rd, rn, 0, rounding_mode); + break; + case "ucvtf_asimdmisc_r"_h: + ucvtf(vform, rd, rn, 0, rounding_mode); + break; + case "ursqrte_asimdmisc_r"_h: + ursqrte(vform, rd, rn); + break; + case "urecpe_asimdmisc_r"_h: + urecpe(vform, rd, rn); + break; + case "frsqrte_asimdmisc_r"_h: + frsqrte(vform, rd, rn); + break; + case "frecpe_asimdmisc_r"_h: + frecpe(vform, rd, rn, rounding_mode); + break; + case "fcmgt_asimdmisc_fz"_h: + fcmp_zero(vform, rd, rn, gt); + break; + case "fcmge_asimdmisc_fz"_h: + fcmp_zero(vform, rd, rn, ge); + break; + case "fcmeq_asimdmisc_fz"_h: + fcmp_zero(vform, rd, rn, eq); + break; + case "fcmle_asimdmisc_fz"_h: + fcmp_zero(vform, rd, rn, le); + break; + case "fcmlt_asimdmisc_fz"_h: + fcmp_zero(vform, rd, rn, lt); + break; + } +} + +void Simulator::VisitNEON2RegMisc(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vf = nfd.GetVectorFormat(); + VectorFormat vf_log = nfd.GetVectorFormat(nfd.LogicalFormatMap()); + + static const NEONFormatMap map_lp = + {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}}; + VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + bool is_q = instr->Mask(NEON_Q) != 0; + + switch (form_hash_) { + case "rev64_asimdmisc_r"_h: + rev64(vf, rd, rn); + break; + case "rev32_asimdmisc_r"_h: + rev32(vf, rd, rn); + break; + case "rev16_asimdmisc_r"_h: + rev16(vf, rd, rn); + break; + case "suqadd_asimdmisc_r"_h: + suqadd(vf, rd, rd, rn); + break; + case "usqadd_asimdmisc_r"_h: + usqadd(vf, rd, rd, rn); + break; + case "cls_asimdmisc_r"_h: + cls(vf, rd, rn); + break; + case "clz_asimdmisc_r"_h: + clz(vf, rd, rn); + break; + case "cnt_asimdmisc_r"_h: + cnt(vf, rd, rn); + break; + case "sqabs_asimdmisc_r"_h: + abs(vf, rd, rn).SignedSaturate(vf); + break; + case "sqneg_asimdmisc_r"_h: + neg(vf, rd, rn).SignedSaturate(vf); + break; + case "cmgt_asimdmisc_z"_h: + cmp(vf, rd, rn, 0, gt); + break; + case "cmge_asimdmisc_z"_h: + cmp(vf, rd, rn, 0, ge); + break; + case "cmeq_asimdmisc_z"_h: + cmp(vf, rd, rn, 0, eq); + break; + case "cmle_asimdmisc_z"_h: + cmp(vf, rd, rn, 0, le); + break; + case "cmlt_asimdmisc_z"_h: + cmp(vf, rd, rn, 0, lt); + break; + case "abs_asimdmisc_r"_h: + abs(vf, rd, rn); + break; + case "neg_asimdmisc_r"_h: + neg(vf, rd, rn); + break; + case "xtn_asimdmisc_n"_h: + xtn(vf, rd, rn); + break; + case "sqxtn_asimdmisc_n"_h: + sqxtn(vf, rd, rn); + break; + case "uqxtn_asimdmisc_n"_h: + uqxtn(vf, rd, rn); + break; + case "sqxtun_asimdmisc_n"_h: + sqxtun(vf, rd, rn); + break; + case "saddlp_asimdmisc_p"_h: + saddlp(vf_lp, rd, rn); + break; + case "uaddlp_asimdmisc_p"_h: + uaddlp(vf_lp, rd, rn); + break; + case "sadalp_asimdmisc_p"_h: + sadalp(vf_lp, rd, rn); + break; + case "uadalp_asimdmisc_p"_h: + uadalp(vf_lp, rd, rn); + break; + case "not_asimdmisc_r"_h: + not_(vf_log, rd, rn); + break; + case "rbit_asimdmisc_r"_h: + rbit(vf_log, rd, rn); + break; + case "shll_asimdmisc_s"_h: + vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap()); + is_q ? shll2(vf, rd, rn) : shll(vf, rd, rn); + break; + } +} + + +void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) { + static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}}; + NEONFormatDecoder nfd(instr); + VectorFormat fpf = nfd.GetVectorFormat(&map_half); + + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (instr->Mask(NEON2RegMiscFP16Mask)) { + case NEON_SCVTF_H: + scvtf(fpf, rd, rn, 0, fpcr_rounding); + return; + case NEON_UCVTF_H: + ucvtf(fpf, rd, rn, 0, fpcr_rounding); + return; + case NEON_FCVTNS_H: + fcvts(fpf, rd, rn, FPTieEven); + return; + case NEON_FCVTNU_H: + fcvtu(fpf, rd, rn, FPTieEven); + return; + case NEON_FCVTPS_H: + fcvts(fpf, rd, rn, FPPositiveInfinity); + return; + case NEON_FCVTPU_H: + fcvtu(fpf, rd, rn, FPPositiveInfinity); + return; + case NEON_FCVTMS_H: + fcvts(fpf, rd, rn, FPNegativeInfinity); + return; + case NEON_FCVTMU_H: + fcvtu(fpf, rd, rn, FPNegativeInfinity); + return; + case NEON_FCVTZS_H: + fcvts(fpf, rd, rn, FPZero); + return; + case NEON_FCVTZU_H: + fcvtu(fpf, rd, rn, FPZero); + return; + case NEON_FCVTAS_H: + fcvts(fpf, rd, rn, FPTieAway); + return; + case NEON_FCVTAU_H: + fcvtu(fpf, rd, rn, FPTieAway); + return; + case NEON_FRINTI_H: + frint(fpf, rd, rn, fpcr_rounding, false); + return; + case NEON_FRINTX_H: + frint(fpf, rd, rn, fpcr_rounding, true); + return; + case NEON_FRINTA_H: + frint(fpf, rd, rn, FPTieAway, false); + return; + case NEON_FRINTM_H: + frint(fpf, rd, rn, FPNegativeInfinity, false); + return; + case NEON_FRINTN_H: + frint(fpf, rd, rn, FPTieEven, false); + return; + case NEON_FRINTP_H: + frint(fpf, rd, rn, FPPositiveInfinity, false); + return; + case NEON_FRINTZ_H: + frint(fpf, rd, rn, FPZero, false); + return; + case NEON_FABS_H: + fabs_(fpf, rd, rn); + return; + case NEON_FNEG_H: + fneg(fpf, rd, rn); + return; + case NEON_FSQRT_H: + fsqrt(fpf, rd, rn); + return; + case NEON_FRSQRTE_H: + frsqrte(fpf, rd, rn); + return; + case NEON_FRECPE_H: + frecpe(fpf, rd, rn, fpcr_rounding); + return; + case NEON_FCMGT_H_zero: + fcmp_zero(fpf, rd, rn, gt); + return; + case NEON_FCMGE_H_zero: + fcmp_zero(fpf, rd, rn, ge); + return; + case NEON_FCMEQ_H_zero: + fcmp_zero(fpf, rd, rn, eq); + return; + case NEON_FCMLE_H_zero: + fcmp_zero(fpf, rd, rn, le); + return; + case NEON_FCMLT_H_zero: + fcmp_zero(fpf, rd, rn, lt); + return; + default: + VIXL_UNIMPLEMENTED(); + return; + } +} + + +void Simulator::VisitNEON3Same(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) { + VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap()); + switch (instr->Mask(NEON3SameLogicalMask)) { + case NEON_AND: + and_(vf, rd, rn, rm); + break; + case NEON_ORR: + orr(vf, rd, rn, rm); + break; + case NEON_ORN: + orn(vf, rd, rn, rm); + break; + case NEON_EOR: + eor(vf, rd, rn, rm); + break; + case NEON_BIC: + bic(vf, rd, rn, rm); + break; + case NEON_BIF: + bif(vf, rd, rn, rm); + break; + case NEON_BIT: + bit(vf, rd, rn, rm); + break; + case NEON_BSL: + bsl(vf, rd, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) { + VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap()); + switch (instr->Mask(NEON3SameFPMask)) { + case NEON_FADD: + fadd(vf, rd, rn, rm); + break; + case NEON_FSUB: + fsub(vf, rd, rn, rm); + break; + case NEON_FMUL: + fmul(vf, rd, rn, rm); + break; + case NEON_FDIV: + fdiv(vf, rd, rn, rm); + break; + case NEON_FMAX: + fmax(vf, rd, rn, rm); + break; + case NEON_FMIN: + fmin(vf, rd, rn, rm); + break; + case NEON_FMAXNM: + fmaxnm(vf, rd, rn, rm); + break; + case NEON_FMINNM: + fminnm(vf, rd, rn, rm); + break; + case NEON_FMLA: + fmla(vf, rd, rd, rn, rm); + break; + case NEON_FMLS: + fmls(vf, rd, rd, rn, rm); + break; + case NEON_FMULX: + fmulx(vf, rd, rn, rm); + break; + case NEON_FACGE: + fabscmp(vf, rd, rn, rm, ge); + break; + case NEON_FACGT: + fabscmp(vf, rd, rn, rm, gt); + break; + case NEON_FCMEQ: + fcmp(vf, rd, rn, rm, eq); + break; + case NEON_FCMGE: + fcmp(vf, rd, rn, rm, ge); + break; + case NEON_FCMGT: + fcmp(vf, rd, rn, rm, gt); + break; + case NEON_FRECPS: + frecps(vf, rd, rn, rm); + break; + case NEON_FRSQRTS: + frsqrts(vf, rd, rn, rm); + break; + case NEON_FABD: + fabd(vf, rd, rn, rm); + break; + case NEON_FADDP: + faddp(vf, rd, rn, rm); + break; + case NEON_FMAXP: + fmaxp(vf, rd, rn, rm); + break; + case NEON_FMAXNMP: + fmaxnmp(vf, rd, rn, rm); + break; + case NEON_FMINP: + fminp(vf, rd, rn, rm); + break; + case NEON_FMINNMP: + fminnmp(vf, rd, rn, rm); + break; + default: + // FMLAL{2} and FMLSL{2} have special-case encodings. + switch (instr->Mask(NEON3SameFHMMask)) { + case NEON_FMLAL: + fmlal(vf, rd, rn, rm); + break; + case NEON_FMLAL2: + fmlal2(vf, rd, rn, rm); + break; + case NEON_FMLSL: + fmlsl(vf, rd, rn, rm); + break; + case NEON_FMLSL2: + fmlsl2(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } + } else { + VectorFormat vf = nfd.GetVectorFormat(); + switch (instr->Mask(NEON3SameMask)) { + case NEON_ADD: + add(vf, rd, rn, rm); + break; + case NEON_ADDP: + addp(vf, rd, rn, rm); + break; + case NEON_CMEQ: + cmp(vf, rd, rn, rm, eq); + break; + case NEON_CMGE: + cmp(vf, rd, rn, rm, ge); + break; + case NEON_CMGT: + cmp(vf, rd, rn, rm, gt); + break; + case NEON_CMHI: + cmp(vf, rd, rn, rm, hi); + break; + case NEON_CMHS: + cmp(vf, rd, rn, rm, hs); + break; + case NEON_CMTST: + cmptst(vf, rd, rn, rm); + break; + case NEON_MLS: + mls(vf, rd, rd, rn, rm); + break; + case NEON_MLA: + mla(vf, rd, rd, rn, rm); + break; + case NEON_MUL: + mul(vf, rd, rn, rm); + break; + case NEON_PMUL: + pmul(vf, rd, rn, rm); + break; + case NEON_SMAX: + smax(vf, rd, rn, rm); + break; + case NEON_SMAXP: + smaxp(vf, rd, rn, rm); + break; + case NEON_SMIN: + smin(vf, rd, rn, rm); + break; + case NEON_SMINP: + sminp(vf, rd, rn, rm); + break; + case NEON_SUB: + sub(vf, rd, rn, rm); + break; + case NEON_UMAX: + umax(vf, rd, rn, rm); + break; + case NEON_UMAXP: + umaxp(vf, rd, rn, rm); + break; + case NEON_UMIN: + umin(vf, rd, rn, rm); + break; + case NEON_UMINP: + uminp(vf, rd, rn, rm); + break; + case NEON_SSHL: + sshl(vf, rd, rn, rm); + break; + case NEON_USHL: + ushl(vf, rd, rn, rm); + break; + case NEON_SABD: + absdiff(vf, rd, rn, rm, true); + break; + case NEON_UABD: + absdiff(vf, rd, rn, rm, false); + break; + case NEON_SABA: + saba(vf, rd, rn, rm); + break; + case NEON_UABA: + uaba(vf, rd, rn, rm); + break; + case NEON_UQADD: + add(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQADD: + add(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_UQSUB: + sub(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQSUB: + sub(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_SQDMULH: + sqdmulh(vf, rd, rn, rm); + break; + case NEON_SQRDMULH: + sqrdmulh(vf, rd, rn, rm); + break; + case NEON_UQSHL: + ushl(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQSHL: + sshl(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_URSHL: + ushl(vf, rd, rn, rm).Round(vf); + break; + case NEON_SRSHL: + sshl(vf, rd, rn, rm).Round(vf); + break; + case NEON_UQRSHL: + ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf); + break; + case NEON_SQRSHL: + sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf); + break; + case NEON_UHADD: + add(vf, rd, rn, rm).Uhalve(vf); + break; + case NEON_URHADD: + add(vf, rd, rn, rm).Uhalve(vf).Round(vf); + break; + case NEON_SHADD: + add(vf, rd, rn, rm).Halve(vf); + break; + case NEON_SRHADD: + add(vf, rd, rn, rm).Halve(vf).Round(vf); + break; + case NEON_UHSUB: + sub(vf, rd, rn, rm).Uhalve(vf); + break; + case NEON_SHSUB: + sub(vf, rd, rn, rm).Halve(vf); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } +} + + +void Simulator::VisitNEON3SameFP16(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap()); + switch (instr->Mask(NEON3SameFP16Mask)) { +#define SIM_FUNC(A, B) \ + case NEON_##A##_H: \ + B(vf, rd, rn, rm); \ + break; + SIM_FUNC(FMAXNM, fmaxnm); + SIM_FUNC(FADD, fadd); + SIM_FUNC(FMULX, fmulx); + SIM_FUNC(FMAX, fmax); + SIM_FUNC(FRECPS, frecps); + SIM_FUNC(FMINNM, fminnm); + SIM_FUNC(FSUB, fsub); + SIM_FUNC(FMIN, fmin); + SIM_FUNC(FRSQRTS, frsqrts); + SIM_FUNC(FMAXNMP, fmaxnmp); + SIM_FUNC(FADDP, faddp); + SIM_FUNC(FMUL, fmul); + SIM_FUNC(FMAXP, fmaxp); + SIM_FUNC(FDIV, fdiv); + SIM_FUNC(FMINNMP, fminnmp); + SIM_FUNC(FABD, fabd); + SIM_FUNC(FMINP, fminp); +#undef SIM_FUNC + case NEON_FMLA_H: + fmla(vf, rd, rd, rn, rm); + break; + case NEON_FMLS_H: + fmls(vf, rd, rd, rn, rm); + break; + case NEON_FCMEQ_H: + fcmp(vf, rd, rn, rm, eq); + break; + case NEON_FCMGE_H: + fcmp(vf, rd, rn, rm, ge); + break; + case NEON_FACGE_H: + fabscmp(vf, rd, rn, rm, ge); + break; + case NEON_FCMGT_H: + fcmp(vf, rd, rn, rm, gt); + break; + case NEON_FACGT_H: + fabscmp(vf, rd, rn, rm, gt); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitNEON3SameExtra(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + int rot = 0; + VectorFormat vf = nfd.GetVectorFormat(); + + switch (form_hash_) { + case "fcmla_asimdsame2_c"_h: + rot = instr->GetImmRotFcmlaVec(); + fcmla(vf, rd, rn, rm, rd, rot); + break; + case "fcadd_asimdsame2_c"_h: + rot = instr->GetImmRotFcadd(); + fcadd(vf, rd, rn, rm, rot); + break; + case "sdot_asimdsame2_d"_h: + sdot(vf, rd, rn, rm); + break; + case "udot_asimdsame2_d"_h: + udot(vf, rd, rn, rm); + break; + case "usdot_asimdsame2_d"_h: + usdot(vf, rd, rn, rm); + break; + case "sqrdmlah_asimdsame2_only"_h: + sqrdmlah(vf, rd, rn, rm); + break; + case "sqrdmlsh_asimdsame2_only"_h: + sqrdmlsh(vf, rd, rn, rm); + break; + } +} + + +void Simulator::VisitNEON3Different(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vf = nfd.GetVectorFormat(); + VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap()); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + int size = instr->GetNEONSize(); + + switch (instr->Mask(NEON3DifferentMask)) { + case NEON_PMULL: + if (size == 3) vf_l = kFormat1Q; + pmull(vf_l, rd, rn, rm); + break; + case NEON_PMULL2: + if (size == 3) vf_l = kFormat1Q; + pmull2(vf_l, rd, rn, rm); + break; + case NEON_UADDL: + uaddl(vf_l, rd, rn, rm); + break; + case NEON_UADDL2: + uaddl2(vf_l, rd, rn, rm); + break; + case NEON_SADDL: + saddl(vf_l, rd, rn, rm); + break; + case NEON_SADDL2: + saddl2(vf_l, rd, rn, rm); + break; + case NEON_USUBL: + usubl(vf_l, rd, rn, rm); + break; + case NEON_USUBL2: + usubl2(vf_l, rd, rn, rm); + break; + case NEON_SSUBL: + ssubl(vf_l, rd, rn, rm); + break; + case NEON_SSUBL2: + ssubl2(vf_l, rd, rn, rm); + break; + case NEON_SABAL: + sabal(vf_l, rd, rn, rm); + break; + case NEON_SABAL2: + sabal2(vf_l, rd, rn, rm); + break; + case NEON_UABAL: + uabal(vf_l, rd, rn, rm); + break; + case NEON_UABAL2: + uabal2(vf_l, rd, rn, rm); + break; + case NEON_SABDL: + sabdl(vf_l, rd, rn, rm); + break; + case NEON_SABDL2: + sabdl2(vf_l, rd, rn, rm); + break; + case NEON_UABDL: + uabdl(vf_l, rd, rn, rm); + break; + case NEON_UABDL2: + uabdl2(vf_l, rd, rn, rm); + break; + case NEON_SMLAL: + smlal(vf_l, rd, rn, rm); + break; + case NEON_SMLAL2: + smlal2(vf_l, rd, rn, rm); + break; + case NEON_UMLAL: + umlal(vf_l, rd, rn, rm); + break; + case NEON_UMLAL2: + umlal2(vf_l, rd, rn, rm); + break; + case NEON_SMLSL: + smlsl(vf_l, rd, rn, rm); + break; + case NEON_SMLSL2: + smlsl2(vf_l, rd, rn, rm); + break; + case NEON_UMLSL: + umlsl(vf_l, rd, rn, rm); + break; + case NEON_UMLSL2: + umlsl2(vf_l, rd, rn, rm); + break; + case NEON_SMULL: + smull(vf_l, rd, rn, rm); + break; + case NEON_SMULL2: + smull2(vf_l, rd, rn, rm); + break; + case NEON_UMULL: + umull(vf_l, rd, rn, rm); + break; + case NEON_UMULL2: + umull2(vf_l, rd, rn, rm); + break; + case NEON_SQDMLAL: + sqdmlal(vf_l, rd, rn, rm); + break; + case NEON_SQDMLAL2: + sqdmlal2(vf_l, rd, rn, rm); + break; + case NEON_SQDMLSL: + sqdmlsl(vf_l, rd, rn, rm); + break; + case NEON_SQDMLSL2: + sqdmlsl2(vf_l, rd, rn, rm); + break; + case NEON_SQDMULL: + sqdmull(vf_l, rd, rn, rm); + break; + case NEON_SQDMULL2: + sqdmull2(vf_l, rd, rn, rm); + break; + case NEON_UADDW: + uaddw(vf_l, rd, rn, rm); + break; + case NEON_UADDW2: + uaddw2(vf_l, rd, rn, rm); + break; + case NEON_SADDW: + saddw(vf_l, rd, rn, rm); + break; + case NEON_SADDW2: + saddw2(vf_l, rd, rn, rm); + break; + case NEON_USUBW: + usubw(vf_l, rd, rn, rm); + break; + case NEON_USUBW2: + usubw2(vf_l, rd, rn, rm); + break; + case NEON_SSUBW: + ssubw(vf_l, rd, rn, rm); + break; + case NEON_SSUBW2: + ssubw2(vf_l, rd, rn, rm); + break; + case NEON_ADDHN: + addhn(vf, rd, rn, rm); + break; + case NEON_ADDHN2: + addhn2(vf, rd, rn, rm); + break; + case NEON_RADDHN: + raddhn(vf, rd, rn, rm); + break; + case NEON_RADDHN2: + raddhn2(vf, rd, rn, rm); + break; + case NEON_SUBHN: + subhn(vf, rd, rn, rm); + break; + case NEON_SUBHN2: + subhn2(vf, rd, rn, rm); + break; + case NEON_RSUBHN: + rsubhn(vf, rd, rn, rm); + break; + case NEON_RSUBHN2: + rsubhn2(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONAcrossLanes(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + + static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}}; + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) { + VectorFormat vf = nfd.GetVectorFormat(&map_half); + switch (instr->Mask(NEONAcrossLanesFP16Mask)) { + case NEON_FMAXV_H: + fmaxv(vf, rd, rn); + break; + case NEON_FMINV_H: + fminv(vf, rd, rn); + break; + case NEON_FMAXNMV_H: + fmaxnmv(vf, rd, rn); + break; + case NEON_FMINNMV_H: + fminnmv(vf, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) { + // The input operand's VectorFormat is passed for these instructions. + VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap()); + + switch (instr->Mask(NEONAcrossLanesFPMask)) { + case NEON_FMAXV: + fmaxv(vf, rd, rn); + break; + case NEON_FMINV: + fminv(vf, rd, rn); + break; + case NEON_FMAXNMV: + fmaxnmv(vf, rd, rn); + break; + case NEON_FMINNMV: + fminnmv(vf, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } else { + VectorFormat vf = nfd.GetVectorFormat(); + + switch (instr->Mask(NEONAcrossLanesMask)) { + case NEON_ADDV: + addv(vf, rd, rn); + break; + case NEON_SMAXV: + smaxv(vf, rd, rn); + break; + case NEON_SMINV: + sminv(vf, rd, rn); + break; + case NEON_UMAXV: + umaxv(vf, rd, rn); + break; + case NEON_UMINV: + uminv(vf, rd, rn); + break; + case NEON_SADDLV: + saddlv(vf, rd, rn); + break; + case NEON_UADDLV: + uaddlv(vf, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } +} + +void Simulator::SimulateNEONMulByElementLong(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap()); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + std::pair rm_and_index = instr->GetNEONMulRmAndIndex(); + SimVRegister temp; + VectorFormat indexform = + VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vf)); + dup_elements_to_segments(indexform, temp, rm_and_index); + + bool is_2 = instr->Mask(NEON_Q) ? true : false; + + switch (form_hash_) { + case "smull_asimdelem_l"_h: + smull(vf, rd, rn, temp, is_2); + break; + case "umull_asimdelem_l"_h: + umull(vf, rd, rn, temp, is_2); + break; + case "smlal_asimdelem_l"_h: + smlal(vf, rd, rn, temp, is_2); + break; + case "umlal_asimdelem_l"_h: + umlal(vf, rd, rn, temp, is_2); + break; + case "smlsl_asimdelem_l"_h: + smlsl(vf, rd, rn, temp, is_2); + break; + case "umlsl_asimdelem_l"_h: + umlsl(vf, rd, rn, temp, is_2); + break; + case "sqdmull_asimdelem_l"_h: + sqdmull(vf, rd, rn, temp, is_2); + break; + case "sqdmlal_asimdelem_l"_h: + sqdmlal(vf, rd, rn, temp, is_2); + break; + case "sqdmlsl_asimdelem_l"_h: + sqdmlsl(vf, rd, rn, temp, is_2); + break; + default: + VIXL_UNREACHABLE(); + } +} + +void Simulator::SimulateNEONFPMulByElementLong(const Instruction* instr) { + VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S; + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRmLow16()); + + int index = + (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM(); + + switch (form_hash_) { + case "fmlal_asimdelem_lh"_h: + fmlal(vform, rd, rn, rm, index); + break; + case "fmlal2_asimdelem_lh"_h: + fmlal2(vform, rd, rn, rm, index); + break; + case "fmlsl_asimdelem_lh"_h: + fmlsl(vform, rd, rn, rm, index); + break; + case "fmlsl2_asimdelem_lh"_h: + fmlsl2(vform, rd, rn, rm, index); + break; + default: + VIXL_UNREACHABLE(); + } +} + +void Simulator::SimulateNEONFPMulByElement(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + static const NEONFormatMap map = + {{23, 22, 30}, + {NF_4H, NF_8H, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S, NF_UNDEF, NF_2D}}; + VectorFormat vform = nfd.GetVectorFormat(&map); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + std::pair rm_and_index = instr->GetNEONMulRmAndIndex(); + SimVRegister& rm = ReadVRegister(rm_and_index.first); + int index = rm_and_index.second; + + switch (form_hash_) { + case "fmul_asimdelem_rh_h"_h: + case "fmul_asimdelem_r_sd"_h: + fmul(vform, rd, rn, rm, index); + break; + case "fmla_asimdelem_rh_h"_h: + case "fmla_asimdelem_r_sd"_h: + fmla(vform, rd, rn, rm, index); + break; + case "fmls_asimdelem_rh_h"_h: + case "fmls_asimdelem_r_sd"_h: + fmls(vform, rd, rn, rm, index); + break; + case "fmulx_asimdelem_rh_h"_h: + case "fmulx_asimdelem_r_sd"_h: + fmulx(vform, rd, rn, rm, index); + break; + default: + VIXL_UNREACHABLE(); + } +} + +void Simulator::SimulateNEONComplexMulByElement(const Instruction* instr) { + VectorFormat vform = instr->GetNEONQ() ? kFormat8H : kFormat4H; + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + int index = (instr->GetNEONH() << 1) | instr->GetNEONL(); + + switch (form_hash_) { + case "fcmla_asimdelem_c_s"_h: + vform = kFormat4S; + index >>= 1; + VIXL_FALLTHROUGH(); + case "fcmla_asimdelem_c_h"_h: + fcmla(vform, rd, rn, rm, index, instr->GetImmRotFcmlaSca()); + break; + default: + VIXL_UNREACHABLE(); + } +} + +void Simulator::SimulateNEONDotProdByElement(const Instruction* instr) { + VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S; + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + int index = (instr->GetNEONH() << 1) | instr->GetNEONL(); + + SimVRegister temp; + // NEON indexed `dot` allows the index value exceed the register size. + // Promote the format to Q-sized vector format before the duplication. + dup_elements_to_segments(VectorFormatFillQ(vform), temp, rm, index); + + switch (form_hash_) { + case "sdot_asimdelem_d"_h: + sdot(vform, rd, rn, temp); + break; + case "udot_asimdelem_d"_h: + udot(vform, rd, rn, temp); + break; + case "sudot_asimdelem_d"_h: + usdot(vform, rd, temp, rn); + break; + case "usdot_asimdelem_d"_h: + usdot(vform, rd, rn, temp); + break; + } +} + +void Simulator::VisitNEONByIndexedElement(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vform = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + std::pair rm_and_index = instr->GetNEONMulRmAndIndex(); + SimVRegister& rm = ReadVRegister(rm_and_index.first); + int index = rm_and_index.second; + + switch (form_hash_) { + case "mul_asimdelem_r"_h: + mul(vform, rd, rn, rm, index); + break; + case "mla_asimdelem_r"_h: + mla(vform, rd, rn, rm, index); + break; + case "mls_asimdelem_r"_h: + mls(vform, rd, rn, rm, index); + break; + case "sqdmulh_asimdelem_r"_h: + sqdmulh(vform, rd, rn, rm, index); + break; + case "sqrdmulh_asimdelem_r"_h: + sqrdmulh(vform, rd, rn, rm, index); + break; + case "sqrdmlah_asimdelem_r"_h: + sqrdmlah(vform, rd, rn, rm, index); + break; + case "sqrdmlsh_asimdelem_r"_h: + sqrdmlsh(vform, rd, rn, rm, index); + break; + } +} + + +void Simulator::VisitNEONCopy(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + int imm5 = instr->GetImmNEON5(); + int tz = CountTrailingZeros(imm5, 32); + int reg_index = ExtractSignedBitfield32(31, tz + 1, imm5); + + if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) { + int imm4 = instr->GetImmNEON4(); + int rn_index = ExtractSignedBitfield32(31, tz, imm4); + mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register. + ins_element(vf, rd, reg_index, rn, rn_index); + } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) { + mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register. + ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn())); + } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) { + uint64_t value = LogicVRegister(rn).Uint(vf, reg_index); + value &= MaxUintFromFormat(vf); + WriteXRegister(instr->GetRd(), value); + } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) { + int64_t value = LogicVRegister(rn).Int(vf, reg_index); + if (instr->GetNEONQ()) { + WriteXRegister(instr->GetRd(), value); + } else { + WriteWRegister(instr->GetRd(), (int32_t)value); + } + } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) { + dup_element(vf, rd, rn, reg_index); + } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) { + dup_immediate(vf, rd, ReadXRegister(instr->GetRn())); + } else { + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONExtract(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + if (instr->Mask(NEONExtractMask) == NEON_EXT) { + int index = instr->GetImmNEONExt(); + ext(vf, rd, rn, rm, index); + } else { + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr, + AddrMode addr_mode) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + int reg_size = RegisterSizeInBytesFromFormat(vf); + + int reg[4]; + uint64_t addr[4]; + for (int i = 0; i < 4; i++) { + reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters; + addr[i] = addr_base + (i * reg_size); + } + int struct_parts = 1; + int reg_count = 1; + bool log_read = true; + + // Bit 23 determines whether this is an offset or post-index addressing mode. + // In offset mode, bits 20 to 16 should be zero; these bits encode the + // register or immediate in post-index mode. + if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) { + VIXL_UNREACHABLE(); + } + + // We use the PostIndex mask here, as it works in this case for both Offset + // and PostIndex addressing. + switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) { + case NEON_LD1_4v: + case NEON_LD1_4v_post: + if (!ld1(vf, ReadVRegister(reg[3]), addr[3])) { + return; + } + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_LD1_3v: + case NEON_LD1_3v_post: + if (!ld1(vf, ReadVRegister(reg[2]), addr[2])) { + return; + } + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_LD1_2v: + case NEON_LD1_2v_post: + if (!ld1(vf, ReadVRegister(reg[1]), addr[1])) { + return; + } + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_LD1_1v: + case NEON_LD1_1v_post: + if (!ld1(vf, ReadVRegister(reg[0]), addr[0])) { + return; + } + break; + case NEON_ST1_4v: + case NEON_ST1_4v_post: + if (!st1(vf, ReadVRegister(reg[3]), addr[3])) return; + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_ST1_3v: + case NEON_ST1_3v_post: + if (!st1(vf, ReadVRegister(reg[2]), addr[2])) return; + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_ST1_2v: + case NEON_ST1_2v_post: + if (!st1(vf, ReadVRegister(reg[1]), addr[1])) return; + reg_count++; + VIXL_FALLTHROUGH(); + case NEON_ST1_1v: + case NEON_ST1_1v_post: + if (!st1(vf, ReadVRegister(reg[0]), addr[0])) return; + log_read = false; + break; + case NEON_LD2_post: + case NEON_LD2: + if (!ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) { + return; + } + struct_parts = 2; + reg_count = 2; + break; + case NEON_ST2: + case NEON_ST2_post: + if (!st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) { + return; + } + struct_parts = 2; + reg_count = 2; + log_read = false; + break; + case NEON_LD3_post: + case NEON_LD3: + if (!ld3(vf, + ReadVRegister(reg[0]), + ReadVRegister(reg[1]), + ReadVRegister(reg[2]), + addr[0])) { + return; + } + struct_parts = 3; + reg_count = 3; + break; + case NEON_ST3: + case NEON_ST3_post: + if (!st3(vf, + ReadVRegister(reg[0]), + ReadVRegister(reg[1]), + ReadVRegister(reg[2]), + addr[0])) { + return; + } + struct_parts = 3; + reg_count = 3; + log_read = false; + break; + case NEON_ST4: + case NEON_ST4_post: + if (!st4(vf, + ReadVRegister(reg[0]), + ReadVRegister(reg[1]), + ReadVRegister(reg[2]), + ReadVRegister(reg[3]), + addr[0])) { + return; + } + struct_parts = 4; + reg_count = 4; + log_read = false; + break; + case NEON_LD4_post: + case NEON_LD4: + if (!ld4(vf, + ReadVRegister(reg[0]), + ReadVRegister(reg[1]), + ReadVRegister(reg[2]), + ReadVRegister(reg[3]), + addr[0])) { + return; + } + struct_parts = 4; + reg_count = 4; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites(); + if (do_trace) { + PrintRegisterFormat print_format = + GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf)); + const char* op; + if (log_read) { + op = "<-"; + } else { + op = "->"; + // Stores don't represent a change to the source register's value, so only + // print the relevant part of the value. + print_format = GetPrintRegPartial(print_format); + } + + VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1)); + for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) { + uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf)); + PrintVStructAccess(reg[s], struct_parts, print_format, op, address); + } + } + + if (addr_mode == PostIndex) { + int rm = instr->GetRm(); + // The immediate post index addressing mode is indicated by rm = 31. + // The immediate is implied by the number of vector registers used. + addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count) + : ReadXRegister(rm); + WriteXRegister(instr->GetRn(), + addr_base, + LogRegWrites, + Reg31IsStackPointer); + } else { + VIXL_ASSERT(addr_mode == Offset); + } +} + + +void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) { + NEONLoadStoreMultiStructHelper(instr, Offset); +} + + +void Simulator::VisitNEONLoadStoreMultiStructPostIndex( + const Instruction* instr) { + NEONLoadStoreMultiStructHelper(instr, PostIndex); +} + + +void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr, + AddrMode addr_mode) { + uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + int rt = instr->GetRt(); + + // Bit 23 determines whether this is an offset or post-index addressing mode. + // In offset mode, bits 20 to 16 should be zero; these bits encode the + // register or immediate in post-index mode. + if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) { + VIXL_UNREACHABLE(); + } + + // We use the PostIndex mask here, as it works in this case for both Offset + // and PostIndex addressing. + bool do_load = false; + + bool replicating = false; + + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap()); + VectorFormat vf_t = nfd.GetVectorFormat(); + + VectorFormat vf = kFormat16B; + switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) { + case NEON_LD1_b: + case NEON_LD1_b_post: + case NEON_LD2_b: + case NEON_LD2_b_post: + case NEON_LD3_b: + case NEON_LD3_b_post: + case NEON_LD4_b: + case NEON_LD4_b_post: + do_load = true; + VIXL_FALLTHROUGH(); + case NEON_ST1_b: + case NEON_ST1_b_post: + case NEON_ST2_b: + case NEON_ST2_b_post: + case NEON_ST3_b: + case NEON_ST3_b_post: + case NEON_ST4_b: + case NEON_ST4_b_post: + break; + + case NEON_LD1_h: + case NEON_LD1_h_post: + case NEON_LD2_h: + case NEON_LD2_h_post: + case NEON_LD3_h: + case NEON_LD3_h_post: + case NEON_LD4_h: + case NEON_LD4_h_post: + do_load = true; + VIXL_FALLTHROUGH(); + case NEON_ST1_h: + case NEON_ST1_h_post: + case NEON_ST2_h: + case NEON_ST2_h_post: + case NEON_ST3_h: + case NEON_ST3_h_post: + case NEON_ST4_h: + case NEON_ST4_h_post: + vf = kFormat8H; + break; + case NEON_LD1_s: + case NEON_LD1_s_post: + case NEON_LD2_s: + case NEON_LD2_s_post: + case NEON_LD3_s: + case NEON_LD3_s_post: + case NEON_LD4_s: + case NEON_LD4_s_post: + do_load = true; + VIXL_FALLTHROUGH(); + case NEON_ST1_s: + case NEON_ST1_s_post: + case NEON_ST2_s: + case NEON_ST2_s_post: + case NEON_ST3_s: + case NEON_ST3_s_post: + case NEON_ST4_s: + case NEON_ST4_s_post: { + VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d); + VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) == + NEON_LD1_d_post); + VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d); + VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) == + NEON_ST1_d_post); + vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D; + break; + } + + case NEON_LD1R: + case NEON_LD1R_post: + case NEON_LD2R: + case NEON_LD2R_post: + case NEON_LD3R: + case NEON_LD3R_post: + case NEON_LD4R: + case NEON_LD4R_post: + vf = vf_t; + do_load = true; + replicating = true; + break; + + default: + VIXL_UNIMPLEMENTED(); + } + + int index_shift = LaneSizeInBytesLog2FromFormat(vf); + int lane = instr->GetNEONLSIndex(index_shift); + int reg_count = 0; + int rt2 = (rt + 1) % kNumberOfVRegisters; + int rt3 = (rt2 + 1) % kNumberOfVRegisters; + int rt4 = (rt3 + 1) % kNumberOfVRegisters; + switch (instr->Mask(NEONLoadStoreSingleLenMask)) { + case NEONLoadStoreSingle1: + reg_count = 1; + if (replicating) { + VIXL_ASSERT(do_load); + if (!ld1r(vf, ReadVRegister(rt), addr)) { + return; + } + } else if (do_load) { + if (!ld1(vf, ReadVRegister(rt), lane, addr)) { + return; + } + } else { + if (!st1(vf, ReadVRegister(rt), lane, addr)) return; + } + break; + case NEONLoadStoreSingle2: + reg_count = 2; + if (replicating) { + VIXL_ASSERT(do_load); + if (!ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr)) { + return; + } + } else if (do_load) { + if (!ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) { + return; + } + } else { + if (!st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) return; + } + break; + case NEONLoadStoreSingle3: + reg_count = 3; + if (replicating) { + VIXL_ASSERT(do_load); + if (!ld3r(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + addr)) { + return; + } + } else if (do_load) { + if (!ld3(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + lane, + addr)) { + return; + } + } else { + if (!st3(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + lane, + addr)) { + return; + } + } + break; + case NEONLoadStoreSingle4: + reg_count = 4; + if (replicating) { + VIXL_ASSERT(do_load); + if (!ld4r(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + ReadVRegister(rt4), + addr)) { + return; + } + } else if (do_load) { + if (!ld4(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + ReadVRegister(rt4), + lane, + addr)) { + return; + } + } else { + if (!st4(vf, + ReadVRegister(rt), + ReadVRegister(rt2), + ReadVRegister(rt3), + ReadVRegister(rt4), + lane, + addr)) { + return; + } + } + break; + default: + VIXL_UNIMPLEMENTED(); + } + + // Trace registers and/or memory writes. + PrintRegisterFormat print_format = + GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf)); + if (do_load) { + if (ShouldTraceVRegs()) { + if (replicating) { + PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr); + } else { + PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr); + } + } + } else { + if (ShouldTraceWrites()) { + // Stores don't represent a change to the source register's value, so only + // print the relevant part of the value. + print_format = GetPrintRegPartial(print_format); + PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr); + } + } + + if (addr_mode == PostIndex) { + int rm = instr->GetRm(); + int lane_size = LaneSizeInBytesFromFormat(vf); + WriteXRegister(instr->GetRn(), + addr + ((rm == 31) ? (reg_count * lane_size) + : ReadXRegister(rm)), + LogRegWrites, + Reg31IsStackPointer); + } +} + + +void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) { + NEONLoadStoreSingleStructHelper(instr, Offset); +} + + +void Simulator::VisitNEONLoadStoreSingleStructPostIndex( + const Instruction* instr) { + NEONLoadStoreSingleStructHelper(instr, PostIndex); +} + + +void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + int cmode = instr->GetNEONCmode(); + int cmode_3_1 = (cmode >> 1) & 7; + int cmode_3 = (cmode >> 3) & 1; + int cmode_2 = (cmode >> 2) & 1; + int cmode_1 = (cmode >> 1) & 1; + int cmode_0 = cmode & 1; + int half_enc = instr->ExtractBit(11); + int q = instr->GetNEONQ(); + int op_bit = instr->GetNEONModImmOp(); + uint64_t imm8 = instr->GetImmNEONabcdefgh(); + // Find the format and immediate value + uint64_t imm = 0; + VectorFormat vform = kFormatUndefined; + switch (cmode_3_1) { + case 0x0: + case 0x1: + case 0x2: + case 0x3: + vform = (q == 1) ? kFormat4S : kFormat2S; + imm = imm8 << (8 * cmode_3_1); + break; + case 0x4: + case 0x5: + vform = (q == 1) ? kFormat8H : kFormat4H; + imm = imm8 << (8 * cmode_1); + break; + case 0x6: + vform = (q == 1) ? kFormat4S : kFormat2S; + if (cmode_0 == 0) { + imm = imm8 << 8 | 0x000000ff; + } else { + imm = imm8 << 16 | 0x0000ffff; + } + break; + case 0x7: + if (cmode_0 == 0 && op_bit == 0) { + vform = q ? kFormat16B : kFormat8B; + imm = imm8; + } else if (cmode_0 == 0 && op_bit == 1) { + vform = q ? kFormat2D : kFormat1D; + imm = 0; + for (int i = 0; i < 8; ++i) { + if (imm8 & (uint64_t{1} << i)) { + imm |= (UINT64_C(0xff) << (8 * i)); + } + } + } else { // cmode_0 == 1, cmode == 0xf. + if (half_enc == 1) { + vform = q ? kFormat8H : kFormat4H; + imm = Float16ToRawbits(instr->GetImmNEONFP16()); + } else if (op_bit == 0) { + vform = q ? kFormat4S : kFormat2S; + imm = FloatToRawbits(instr->GetImmNEONFP32()); + } else if (q == 1) { + vform = kFormat2D; + imm = DoubleToRawbits(instr->GetImmNEONFP64()); + } + } + break; + default: + VIXL_UNREACHABLE(); + break; + } + + // Find the operation + NEONModifiedImmediateOp op; + if (cmode_3 == 0) { + if (cmode_0 == 0) { + op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI; + } else { // cmode<0> == '1' + op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR; + } + } else { // cmode<3> == '1' + if (cmode_2 == 0) { + if (cmode_0 == 0) { + op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI; + } else { // cmode<0> == '1' + op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR; + } + } else { // cmode<2> == '1' + if (cmode_1 == 0) { + op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI; + } else { // cmode<1> == '1' + if (cmode_0 == 0) { + op = NEONModifiedImmediate_MOVI; + } else { // cmode<0> == '1' + op = NEONModifiedImmediate_MOVI; + } + } + } + } + + // Call the logic function + if (op == NEONModifiedImmediate_ORR) { + orr(vform, rd, rd, imm); + } else if (op == NEONModifiedImmediate_BIC) { + bic(vform, rd, rd, imm); + } else if (op == NEONModifiedImmediate_MOVI) { + movi(vform, rd, imm); + } else if (op == NEONModifiedImmediate_MVNI) { + mvni(vform, rd, imm); + } else { + VisitUnimplemented(instr); + } +} + + +void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) { + // These instructions all use a two bit size field, except NOT and RBIT, + // which use the field to encode the operation. + switch (instr->Mask(NEONScalar2RegMiscMask)) { + case NEON_CMEQ_zero_scalar: + cmp(vf, rd, rn, 0, eq); + break; + case NEON_CMGE_zero_scalar: + cmp(vf, rd, rn, 0, ge); + break; + case NEON_CMGT_zero_scalar: + cmp(vf, rd, rn, 0, gt); + break; + case NEON_CMLT_zero_scalar: + cmp(vf, rd, rn, 0, lt); + break; + case NEON_CMLE_zero_scalar: + cmp(vf, rd, rn, 0, le); + break; + case NEON_ABS_scalar: + abs(vf, rd, rn); + break; + case NEON_SQABS_scalar: + abs(vf, rd, rn).SignedSaturate(vf); + break; + case NEON_NEG_scalar: + neg(vf, rd, rn); + break; + case NEON_SQNEG_scalar: + neg(vf, rd, rn).SignedSaturate(vf); + break; + case NEON_SUQADD_scalar: + suqadd(vf, rd, rd, rn); + break; + case NEON_USQADD_scalar: + usqadd(vf, rd, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } else { + VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap()); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + // These instructions all use a one bit size field, except SQXTUN, SQXTN + // and UQXTN, which use a two bit size field. + switch (instr->Mask(NEONScalar2RegMiscFPMask)) { + case NEON_FRECPE_scalar: + frecpe(fpf, rd, rn, fpcr_rounding); + break; + case NEON_FRECPX_scalar: + frecpx(fpf, rd, rn); + break; + case NEON_FRSQRTE_scalar: + frsqrte(fpf, rd, rn); + break; + case NEON_FCMGT_zero_scalar: + fcmp_zero(fpf, rd, rn, gt); + break; + case NEON_FCMGE_zero_scalar: + fcmp_zero(fpf, rd, rn, ge); + break; + case NEON_FCMEQ_zero_scalar: + fcmp_zero(fpf, rd, rn, eq); + break; + case NEON_FCMLE_zero_scalar: + fcmp_zero(fpf, rd, rn, le); + break; + case NEON_FCMLT_zero_scalar: + fcmp_zero(fpf, rd, rn, lt); + break; + case NEON_SCVTF_scalar: + scvtf(fpf, rd, rn, 0, fpcr_rounding); + break; + case NEON_UCVTF_scalar: + ucvtf(fpf, rd, rn, 0, fpcr_rounding); + break; + case NEON_FCVTNS_scalar: + fcvts(fpf, rd, rn, FPTieEven); + break; + case NEON_FCVTNU_scalar: + fcvtu(fpf, rd, rn, FPTieEven); + break; + case NEON_FCVTPS_scalar: + fcvts(fpf, rd, rn, FPPositiveInfinity); + break; + case NEON_FCVTPU_scalar: + fcvtu(fpf, rd, rn, FPPositiveInfinity); + break; + case NEON_FCVTMS_scalar: + fcvts(fpf, rd, rn, FPNegativeInfinity); + break; + case NEON_FCVTMU_scalar: + fcvtu(fpf, rd, rn, FPNegativeInfinity); + break; + case NEON_FCVTZS_scalar: + fcvts(fpf, rd, rn, FPZero); + break; + case NEON_FCVTZU_scalar: + fcvtu(fpf, rd, rn, FPZero); + break; + case NEON_FCVTAS_scalar: + fcvts(fpf, rd, rn, FPTieAway); + break; + case NEON_FCVTAU_scalar: + fcvtu(fpf, rd, rn, FPTieAway); + break; + case NEON_FCVTXN_scalar: + // Unlike all of the other FP instructions above, fcvtxn encodes dest + // size S as size<0>=1. There's only one case, so we ignore the form. + VIXL_ASSERT(instr->ExtractBit(22) == 1); + fcvtxn(kFormatS, rd, rn); + break; + default: + switch (instr->Mask(NEONScalar2RegMiscMask)) { + case NEON_SQXTN_scalar: + sqxtn(vf, rd, rn); + break; + case NEON_UQXTN_scalar: + uqxtn(vf, rd, rn); + break; + case NEON_SQXTUN_scalar: + sqxtun(vf, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } + } +} + + +void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) { + VectorFormat fpf = kFormatH; + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) { + case NEON_FRECPE_H_scalar: + frecpe(fpf, rd, rn, fpcr_rounding); + break; + case NEON_FRECPX_H_scalar: + frecpx(fpf, rd, rn); + break; + case NEON_FRSQRTE_H_scalar: + frsqrte(fpf, rd, rn); + break; + case NEON_FCMGT_H_zero_scalar: + fcmp_zero(fpf, rd, rn, gt); + break; + case NEON_FCMGE_H_zero_scalar: + fcmp_zero(fpf, rd, rn, ge); + break; + case NEON_FCMEQ_H_zero_scalar: + fcmp_zero(fpf, rd, rn, eq); + break; + case NEON_FCMLE_H_zero_scalar: + fcmp_zero(fpf, rd, rn, le); + break; + case NEON_FCMLT_H_zero_scalar: + fcmp_zero(fpf, rd, rn, lt); + break; + case NEON_SCVTF_H_scalar: + scvtf(fpf, rd, rn, 0, fpcr_rounding); + break; + case NEON_UCVTF_H_scalar: + ucvtf(fpf, rd, rn, 0, fpcr_rounding); + break; + case NEON_FCVTNS_H_scalar: + fcvts(fpf, rd, rn, FPTieEven); + break; + case NEON_FCVTNU_H_scalar: + fcvtu(fpf, rd, rn, FPTieEven); + break; + case NEON_FCVTPS_H_scalar: + fcvts(fpf, rd, rn, FPPositiveInfinity); + break; + case NEON_FCVTPU_H_scalar: + fcvtu(fpf, rd, rn, FPPositiveInfinity); + break; + case NEON_FCVTMS_H_scalar: + fcvts(fpf, rd, rn, FPNegativeInfinity); + break; + case NEON_FCVTMU_H_scalar: + fcvtu(fpf, rd, rn, FPNegativeInfinity); + break; + case NEON_FCVTZS_H_scalar: + fcvts(fpf, rd, rn, FPZero); + break; + case NEON_FCVTZU_H_scalar: + fcvtu(fpf, rd, rn, FPZero); + break; + case NEON_FCVTAS_H_scalar: + fcvts(fpf, rd, rn, FPTieAway); + break; + case NEON_FCVTAU_H_scalar: + fcvtu(fpf, rd, rn, FPTieAway); + break; + } +} + + +void Simulator::VisitNEONScalar3Diff(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + switch (instr->Mask(NEONScalar3DiffMask)) { + case NEON_SQDMLAL_scalar: + sqdmlal(vf, rd, rn, rm); + break; + case NEON_SQDMLSL_scalar: + sqdmlsl(vf, rd, rn, rm); + break; + case NEON_SQDMULL_scalar: + sqdmull(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONScalar3Same(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) { + vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap()); + switch (instr->Mask(NEONScalar3SameFPMask)) { + case NEON_FMULX_scalar: + fmulx(vf, rd, rn, rm); + break; + case NEON_FACGE_scalar: + fabscmp(vf, rd, rn, rm, ge); + break; + case NEON_FACGT_scalar: + fabscmp(vf, rd, rn, rm, gt); + break; + case NEON_FCMEQ_scalar: + fcmp(vf, rd, rn, rm, eq); + break; + case NEON_FCMGE_scalar: + fcmp(vf, rd, rn, rm, ge); + break; + case NEON_FCMGT_scalar: + fcmp(vf, rd, rn, rm, gt); + break; + case NEON_FRECPS_scalar: + frecps(vf, rd, rn, rm); + break; + case NEON_FRSQRTS_scalar: + frsqrts(vf, rd, rn, rm); + break; + case NEON_FABD_scalar: + fabd(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } else { + switch (instr->Mask(NEONScalar3SameMask)) { + case NEON_ADD_scalar: + add(vf, rd, rn, rm); + break; + case NEON_SUB_scalar: + sub(vf, rd, rn, rm); + break; + case NEON_CMEQ_scalar: + cmp(vf, rd, rn, rm, eq); + break; + case NEON_CMGE_scalar: + cmp(vf, rd, rn, rm, ge); + break; + case NEON_CMGT_scalar: + cmp(vf, rd, rn, rm, gt); + break; + case NEON_CMHI_scalar: + cmp(vf, rd, rn, rm, hi); + break; + case NEON_CMHS_scalar: + cmp(vf, rd, rn, rm, hs); + break; + case NEON_CMTST_scalar: + cmptst(vf, rd, rn, rm); + break; + case NEON_USHL_scalar: + ushl(vf, rd, rn, rm); + break; + case NEON_SSHL_scalar: + sshl(vf, rd, rn, rm); + break; + case NEON_SQDMULH_scalar: + sqdmulh(vf, rd, rn, rm); + break; + case NEON_SQRDMULH_scalar: + sqrdmulh(vf, rd, rn, rm); + break; + case NEON_UQADD_scalar: + add(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQADD_scalar: + add(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_UQSUB_scalar: + sub(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQSUB_scalar: + sub(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_UQSHL_scalar: + ushl(vf, rd, rn, rm).UnsignedSaturate(vf); + break; + case NEON_SQSHL_scalar: + sshl(vf, rd, rn, rm).SignedSaturate(vf); + break; + case NEON_URSHL_scalar: + ushl(vf, rd, rn, rm).Round(vf); + break; + case NEON_SRSHL_scalar: + sshl(vf, rd, rn, rm).Round(vf); + break; + case NEON_UQRSHL_scalar: + ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf); + break; + case NEON_SQRSHL_scalar: + sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } +} + +void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(NEONScalar3SameFP16Mask)) { + case NEON_FABD_H_scalar: + fabd(kFormatH, rd, rn, rm); + break; + case NEON_FMULX_H_scalar: + fmulx(kFormatH, rd, rn, rm); + break; + case NEON_FCMEQ_H_scalar: + fcmp(kFormatH, rd, rn, rm, eq); + break; + case NEON_FCMGE_H_scalar: + fcmp(kFormatH, rd, rn, rm, ge); + break; + case NEON_FCMGT_H_scalar: + fcmp(kFormatH, rd, rn, rm, gt); + break; + case NEON_FACGE_H_scalar: + fabscmp(kFormatH, rd, rn, rm, ge); + break; + case NEON_FACGT_H_scalar: + fabscmp(kFormatH, rd, rn, rm, gt); + break; + case NEON_FRECPS_H_scalar: + frecps(kFormatH, rd, rn, rm); + break; + case NEON_FRSQRTS_H_scalar: + frsqrts(kFormatH, rd, rn, rm); + break; + default: + VIXL_UNREACHABLE(); + } +} + + +void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(NEONScalar3SameExtraMask)) { + case NEON_SQRDMLAH_scalar: + sqrdmlah(vf, rd, rn, rm); + break; + case NEON_SQRDMLSH_scalar: + sqrdmlsh(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + ByElementOp Op = NULL; + + std::pair rm_and_index = instr->GetNEONMulRmAndIndex(); + std::unordered_map handler = { + {"sqdmull_asisdelem_l"_h, &Simulator::sqdmull}, + {"sqdmlal_asisdelem_l"_h, &Simulator::sqdmlal}, + {"sqdmlsl_asisdelem_l"_h, &Simulator::sqdmlsl}, + {"sqdmulh_asisdelem_r"_h, &Simulator::sqdmulh}, + {"sqrdmulh_asisdelem_r"_h, &Simulator::sqrdmulh}, + {"sqrdmlah_asisdelem_r"_h, &Simulator::sqrdmlah}, + {"sqrdmlsh_asisdelem_r"_h, &Simulator::sqrdmlsh}, + {"fmul_asisdelem_rh_h"_h, &Simulator::fmul}, + {"fmul_asisdelem_r_sd"_h, &Simulator::fmul}, + {"fmla_asisdelem_rh_h"_h, &Simulator::fmla}, + {"fmla_asisdelem_r_sd"_h, &Simulator::fmla}, + {"fmls_asisdelem_rh_h"_h, &Simulator::fmls}, + {"fmls_asisdelem_r_sd"_h, &Simulator::fmls}, + {"fmulx_asisdelem_rh_h"_h, &Simulator::fmulx}, + {"fmulx_asisdelem_r_sd"_h, &Simulator::fmulx}, + }; + + std::unordered_map::const_iterator it = + handler.find(form_hash_); + + if (it == handler.end()) { + VIXL_UNIMPLEMENTED(); + } else { + Op = it->second; + } + + switch (form_hash_) { + case "sqdmulh_asisdelem_r"_h: + case "sqrdmulh_asisdelem_r"_h: + case "sqrdmlah_asisdelem_r"_h: + case "sqrdmlsh_asisdelem_r"_h: + vf = nfd.GetVectorFormat(nfd.ScalarFormatMap()); + break; + case "fmul_asisdelem_r_sd"_h: + case "fmla_asisdelem_r_sd"_h: + case "fmls_asisdelem_r_sd"_h: + case "fmulx_asisdelem_r_sd"_h: + vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap()); + break; + case "fmul_asisdelem_rh_h"_h: + case "fmla_asisdelem_rh_h"_h: + case "fmls_asisdelem_rh_h"_h: + case "fmulx_asisdelem_rh_h"_h: + vf = kFormatH; + break; + } + + (this->*Op)(vf, + rd, + rn, + ReadVRegister(rm_and_index.first), + rm_and_index.second); +} + + +void Simulator::VisitNEONScalarCopy(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + + if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) { + int imm5 = instr->GetImmNEON5(); + int tz = CountTrailingZeros(imm5, 32); + int rn_index = ExtractSignedBitfield32(31, tz + 1, imm5); + dup_element(vf, rd, rn, rn_index); + } else { + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONScalarPairwise(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + switch (instr->Mask(NEONScalarPairwiseMask)) { + case NEON_ADDP_scalar: { + // All pairwise operations except ADDP use bit U to differentiate FP16 + // from FP32/FP64 variations. + NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap()); + addp(nfd_addp.GetVectorFormat(), rd, rn); + break; + } + case NEON_FADDP_h_scalar: + case NEON_FADDP_scalar: + faddp(vf, rd, rn); + break; + case NEON_FMAXP_h_scalar: + case NEON_FMAXP_scalar: + fmaxp(vf, rd, rn); + break; + case NEON_FMAXNMP_h_scalar: + case NEON_FMAXNMP_scalar: + fmaxnmp(vf, rd, rn); + break; + case NEON_FMINP_h_scalar: + case NEON_FMINP_scalar: + fminp(vf, rd, rn); + break; + case NEON_FMINNMP_h_scalar: + case NEON_FMINNMP_scalar: + fminnmp(vf, rd, rn); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + static const NEONFormatMap map = {{22, 21, 20, 19}, + {NF_UNDEF, + NF_B, + NF_H, + NF_H, + NF_S, + NF_S, + NF_S, + NF_S, + NF_D, + NF_D, + NF_D, + NF_D, + NF_D, + NF_D, + NF_D, + NF_D}}; + NEONFormatDecoder nfd(instr, &map); + VectorFormat vf = nfd.GetVectorFormat(); + + int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh()); + int immh_immb = instr->GetImmNEONImmhImmb(); + int right_shift = (16 << highest_set_bit) - immh_immb; + int left_shift = immh_immb - (8 << highest_set_bit); + switch (instr->Mask(NEONScalarShiftImmediateMask)) { + case NEON_SHL_scalar: + shl(vf, rd, rn, left_shift); + break; + case NEON_SLI_scalar: + sli(vf, rd, rn, left_shift); + break; + case NEON_SQSHL_imm_scalar: + sqshl(vf, rd, rn, left_shift); + break; + case NEON_UQSHL_imm_scalar: + uqshl(vf, rd, rn, left_shift); + break; + case NEON_SQSHLU_scalar: + sqshlu(vf, rd, rn, left_shift); + break; + case NEON_SRI_scalar: + sri(vf, rd, rn, right_shift); + break; + case NEON_SSHR_scalar: + sshr(vf, rd, rn, right_shift); + break; + case NEON_USHR_scalar: + ushr(vf, rd, rn, right_shift); + break; + case NEON_SRSHR_scalar: + sshr(vf, rd, rn, right_shift).Round(vf); + break; + case NEON_URSHR_scalar: + ushr(vf, rd, rn, right_shift).Round(vf); + break; + case NEON_SSRA_scalar: + ssra(vf, rd, rn, right_shift); + break; + case NEON_USRA_scalar: + usra(vf, rd, rn, right_shift); + break; + case NEON_SRSRA_scalar: + srsra(vf, rd, rn, right_shift); + break; + case NEON_URSRA_scalar: + ursra(vf, rd, rn, right_shift); + break; + case NEON_UQSHRN_scalar: + uqshrn(vf, rd, rn, right_shift); + break; + case NEON_UQRSHRN_scalar: + uqrshrn(vf, rd, rn, right_shift); + break; + case NEON_SQSHRN_scalar: + sqshrn(vf, rd, rn, right_shift); + break; + case NEON_SQRSHRN_scalar: + sqrshrn(vf, rd, rn, right_shift); + break; + case NEON_SQSHRUN_scalar: + sqshrun(vf, rd, rn, right_shift); + break; + case NEON_SQRSHRUN_scalar: + sqrshrun(vf, rd, rn, right_shift); + break; + case NEON_FCVTZS_imm_scalar: + fcvts(vf, rd, rn, FPZero, right_shift); + break; + case NEON_FCVTZU_imm_scalar: + fcvtu(vf, rd, rn, FPZero, right_shift); + break; + case NEON_SCVTF_imm_scalar: + scvtf(vf, rd, rn, right_shift, fpcr_rounding); + break; + case NEON_UCVTF_imm_scalar: + ucvtf(vf, rd, rn, right_shift, fpcr_rounding); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONShiftImmediate(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H, + // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined. + static const NEONFormatMap map = {{22, 21, 20, 19, 30}, + {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, + NF_4H, NF_8H, NF_4H, NF_8H, + NF_2S, NF_4S, NF_2S, NF_4S, + NF_2S, NF_4S, NF_2S, NF_4S, + NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, + NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, + NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, + NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}}; + NEONFormatDecoder nfd(instr, &map); + VectorFormat vf = nfd.GetVectorFormat(); + + // 0001->8H, 001x->4S, 01xx->2D, all others undefined. + static const NEONFormatMap map_l = + {{22, 21, 20, 19}, + {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}}; + VectorFormat vf_l = nfd.GetVectorFormat(&map_l); + + int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh()); + int immh_immb = instr->GetImmNEONImmhImmb(); + int right_shift = (16 << highest_set_bit) - immh_immb; + int left_shift = immh_immb - (8 << highest_set_bit); + + switch (instr->Mask(NEONShiftImmediateMask)) { + case NEON_SHL: + shl(vf, rd, rn, left_shift); + break; + case NEON_SLI: + sli(vf, rd, rn, left_shift); + break; + case NEON_SQSHLU: + sqshlu(vf, rd, rn, left_shift); + break; + case NEON_SRI: + sri(vf, rd, rn, right_shift); + break; + case NEON_SSHR: + sshr(vf, rd, rn, right_shift); + break; + case NEON_USHR: + ushr(vf, rd, rn, right_shift); + break; + case NEON_SRSHR: + sshr(vf, rd, rn, right_shift).Round(vf); + break; + case NEON_URSHR: + ushr(vf, rd, rn, right_shift).Round(vf); + break; + case NEON_SSRA: + ssra(vf, rd, rn, right_shift); + break; + case NEON_USRA: + usra(vf, rd, rn, right_shift); + break; + case NEON_SRSRA: + srsra(vf, rd, rn, right_shift); + break; + case NEON_URSRA: + ursra(vf, rd, rn, right_shift); + break; + case NEON_SQSHL_imm: + sqshl(vf, rd, rn, left_shift); + break; + case NEON_UQSHL_imm: + uqshl(vf, rd, rn, left_shift); + break; + case NEON_SCVTF_imm: + scvtf(vf, rd, rn, right_shift, fpcr_rounding); + break; + case NEON_UCVTF_imm: + ucvtf(vf, rd, rn, right_shift, fpcr_rounding); + break; + case NEON_FCVTZS_imm: + fcvts(vf, rd, rn, FPZero, right_shift); + break; + case NEON_FCVTZU_imm: + fcvtu(vf, rd, rn, FPZero, right_shift); + break; + case NEON_SSHLL: + vf = vf_l; + if (instr->Mask(NEON_Q)) { + sshll2(vf, rd, rn, left_shift); + } else { + sshll(vf, rd, rn, left_shift); + } + break; + case NEON_USHLL: + vf = vf_l; + if (instr->Mask(NEON_Q)) { + ushll2(vf, rd, rn, left_shift); + } else { + ushll(vf, rd, rn, left_shift); + } + break; + case NEON_SHRN: + if (instr->Mask(NEON_Q)) { + shrn2(vf, rd, rn, right_shift); + } else { + shrn(vf, rd, rn, right_shift); + } + break; + case NEON_RSHRN: + if (instr->Mask(NEON_Q)) { + rshrn2(vf, rd, rn, right_shift); + } else { + rshrn(vf, rd, rn, right_shift); + } + break; + case NEON_UQSHRN: + if (instr->Mask(NEON_Q)) { + uqshrn2(vf, rd, rn, right_shift); + } else { + uqshrn(vf, rd, rn, right_shift); + } + break; + case NEON_UQRSHRN: + if (instr->Mask(NEON_Q)) { + uqrshrn2(vf, rd, rn, right_shift); + } else { + uqrshrn(vf, rd, rn, right_shift); + } + break; + case NEON_SQSHRN: + if (instr->Mask(NEON_Q)) { + sqshrn2(vf, rd, rn, right_shift); + } else { + sqshrn(vf, rd, rn, right_shift); + } + break; + case NEON_SQRSHRN: + if (instr->Mask(NEON_Q)) { + sqrshrn2(vf, rd, rn, right_shift); + } else { + sqrshrn(vf, rd, rn, right_shift); + } + break; + case NEON_SQSHRUN: + if (instr->Mask(NEON_Q)) { + sqshrun2(vf, rd, rn, right_shift); + } else { + sqshrun(vf, rd, rn, right_shift); + } + break; + case NEON_SQRSHRUN: + if (instr->Mask(NEON_Q)) { + sqrshrun2(vf, rd, rn, right_shift); + } else { + sqrshrun(vf, rd, rn, right_shift); + } + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONTable(const Instruction* instr) { + NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap()); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters); + SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters); + SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(NEONTableMask)) { + case NEON_TBL_1v: + tbl(vf, rd, rn, rm); + break; + case NEON_TBL_2v: + tbl(vf, rd, rn, rn2, rm); + break; + case NEON_TBL_3v: + tbl(vf, rd, rn, rn2, rn3, rm); + break; + case NEON_TBL_4v: + tbl(vf, rd, rn, rn2, rn3, rn4, rm); + break; + case NEON_TBX_1v: + tbx(vf, rd, rn, rm); + break; + case NEON_TBX_2v: + tbx(vf, rd, rn, rn2, rm); + break; + case NEON_TBX_3v: + tbx(vf, rd, rn, rn2, rn3, rm); + break; + case NEON_TBX_4v: + tbx(vf, rd, rn, rn2, rn3, rn4, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + + +void Simulator::VisitNEONPerm(const Instruction* instr) { + NEONFormatDecoder nfd(instr); + VectorFormat vf = nfd.GetVectorFormat(); + + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(NEONPermMask)) { + case NEON_TRN1: + trn1(vf, rd, rn, rm); + break; + case NEON_TRN2: + trn2(vf, rd, rn, rm); + break; + case NEON_UZP1: + uzp1(vf, rd, rn, rm); + break; + case NEON_UZP2: + uzp2(vf, rd, rn, rm); + break; + case NEON_ZIP1: + zip1(vf, rd, rn, rm); + break; + case NEON_ZIP2: + zip2(vf, rd, rn, rm); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::SimulateNEONSHA3(const Instruction* instr) { + SimVRegister& rd = ReadVRegister(instr->GetRd()); + SimVRegister& rn = ReadVRegister(instr->GetRn()); + SimVRegister& rm = ReadVRegister(instr->GetRm()); + SimVRegister& ra = ReadVRegister(instr->GetRa()); + SimVRegister temp; + + switch (form_hash_) { + case "bcax_vvv16_crypto4"_h: + bic(kFormat16B, temp, rm, ra); + eor(kFormat16B, rd, rn, temp); + break; + case "eor3_vvv16_crypto4"_h: + eor(kFormat16B, temp, rm, ra); + eor(kFormat16B, rd, rn, temp); + break; + case "rax1_vvv2_cryptosha512_3"_h: + ror(kFormat2D, temp, rm, 63); // rol(1) => ror(63) + eor(kFormat2D, rd, rn, temp); + break; + case "xar_vvv2_crypto3_imm6"_h: + int rot = instr->ExtractBits(15, 10); + eor(kFormat2D, temp, rn, rm); + ror(kFormat2D, rd, temp, rot); + break; + } +} + +void Simulator::VisitSVEAddressGeneration(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister temp; + + VectorFormat vform = kFormatVnD; + mov(vform, temp, zm); + + switch (instr->Mask(SVEAddressGenerationMask)) { + case ADR_z_az_d_s32_scaled: + sxt(vform, temp, temp, kSRegSize); + break; + case ADR_z_az_d_u32_scaled: + uxt(vform, temp, temp, kSRegSize); + break; + case ADR_z_az_s_same_scaled: + vform = kFormatVnS; + break; + case ADR_z_az_d_same_scaled: + // Nothing to do. + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + int shift_amount = instr->ExtractBits(11, 10); + shl(vform, temp, temp, shift_amount); + add(vform, zd, zn, temp); +} + +void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated( + const Instruction* instr) { + Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask); + switch (op) { + case AND_z_zi: + case EOR_z_zi: + case ORR_z_zi: { + int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2(); + uint64_t imm = instr->GetSVEImmLogical(); + // Valid immediate is a non-zero bits + VIXL_ASSERT(imm != 0); + SVEBitwiseImmHelper(static_cast( + op), + SVEFormatFromLaneSizeInBytesLog2(lane_size), + ReadVRegister(instr->GetRd()), + imm); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) { + switch (instr->Mask(SVEBroadcastBitmaskImmMask)) { + case DUPM_z_i: { + /* DUPM uses the same lane size and immediate encoding as bitwise logical + * immediate instructions. */ + int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2(); + uint64_t imm = instr->GetSVEImmLogical(); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + dup_immediate(vform, ReadVRegister(instr->GetRd()), imm); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask); + + LogicalOp logical_op = LogicalOpMask; + switch (op) { + case AND_z_zz: + logical_op = AND; + break; + case BIC_z_zz: + logical_op = BIC; + break; + case EOR_z_zz: + logical_op = EOR; + break; + case ORR_z_zz: + logical_op = ORR; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + // Lane size of registers is irrelevant to the bitwise operations, so perform + // the operation on D-sized lanes. + SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm); +} + +void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) { + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + SimVRegister scratch; + SimVRegister result; + + bool for_division = false; + Shift shift_op = NO_SHIFT; + switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) { + case ASRD_z_p_zi: + shift_op = ASR; + for_division = true; + break; + case ASR_z_p_zi: + shift_op = ASR; + break; + case LSL_z_p_zi: + shift_op = LSL; + break; + case LSR_z_p_zi: + shift_op = LSR; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true); + unsigned lane_size = shift_and_lane_size.second; + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int shift_dist = shift_and_lane_size.first; + + if ((shift_op == ASR) && for_division) { + asrd(vform, result, zdn, shift_dist); + } else { + if (shift_op == LSL) { + // Shift distance is computed differently for LSL. Convert the result. + shift_dist = (8 << lane_size) - shift_dist; + } + dup_immediate(vform, scratch, shift_dist); + SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false); + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEBitwiseShiftByVector_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + // SVE uses the whole (saturated) lane for the shift amount. + bool shift_in_ls_byte = false; + + switch (form_hash_) { + case "asrr_z_p_zz"_h: + sshr(vform, result, zm, zdn); + break; + case "asr_z_p_zz"_h: + sshr(vform, result, zdn, zm); + break; + case "lslr_z_p_zz"_h: + sshl(vform, result, zm, zdn, shift_in_ls_byte); + break; + case "lsl_z_p_zz"_h: + sshl(vform, result, zdn, zm, shift_in_ls_byte); + break; + case "lsrr_z_p_zz"_h: + ushr(vform, result, zm, zdn); + break; + case "lsr_z_p_zz"_h: + ushr(vform, result, zdn, zm); + break; + case "sqrshl_z_p_zz"_h: + sshl(vform, result, zdn, zm, shift_in_ls_byte) + .Round(vform) + .SignedSaturate(vform); + break; + case "sqrshlr_z_p_zz"_h: + sshl(vform, result, zm, zdn, shift_in_ls_byte) + .Round(vform) + .SignedSaturate(vform); + break; + case "sqshl_z_p_zz"_h: + sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform); + break; + case "sqshlr_z_p_zz"_h: + sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform); + break; + case "srshl_z_p_zz"_h: + sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform); + break; + case "srshlr_z_p_zz"_h: + sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform); + break; + case "uqrshl_z_p_zz"_h: + ushl(vform, result, zdn, zm, shift_in_ls_byte) + .Round(vform) + .UnsignedSaturate(vform); + break; + case "uqrshlr_z_p_zz"_h: + ushl(vform, result, zm, zdn, shift_in_ls_byte) + .Round(vform) + .UnsignedSaturate(vform); + break; + case "uqshl_z_p_zz"_h: + ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform); + break; + case "uqshlr_z_p_zz"_h: + ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform); + break; + case "urshl_z_p_zz"_h: + ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform); + break; + case "urshlr_z_p_zz"_h: + ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + SimVRegister result; + Shift shift_op = ASR; + + switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) { + case ASR_z_p_zw: + break; + case LSL_z_p_zw: + shift_op = LSL; + break; + case LSR_z_p_zw: + shift_op = LSR; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + SVEBitwiseShiftHelper(shift_op, + vform, + result, + zdn, + zm, + /* is_wide_elements = */ true); + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + Shift shift_op = NO_SHIFT; + switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) { + case ASR_z_zi: + case ASR_z_zw: + shift_op = ASR; + break; + case LSL_z_zi: + case LSL_z_zw: + shift_op = LSL; + break; + case LSR_z_zi: + case LSR_z_zw: + shift_op = LSR; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) { + case ASR_z_zi: + case LSL_z_zi: + case LSR_z_zi: { + SimVRegister scratch; + std::pair shift_and_lane_size = + instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false); + unsigned lane_size = shift_and_lane_size.second; + VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size); + int shift_dist = shift_and_lane_size.first; + if (shift_op == LSL) { + // Shift distance is computed differently for LSL. Convert the result. + shift_dist = (8 << lane_size) - shift_dist; + } + dup_immediate(vform, scratch, shift_dist); + SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false); + break; + } + case ASR_z_zw: + case LSL_z_zw: + case LSR_z_zw: + SVEBitwiseShiftHelper(shift_op, + instr->GetSVEVectorFormat(), + zd, + zn, + ReadVRegister(instr->GetRm()), + true); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) { + // Although the instructions have a separate encoding class, the lane size is + // encoded in the same way as most other SVE instructions. + VectorFormat vform = instr->GetSVEVectorFormat(); + + int pattern = instr->GetImmSVEPredicateConstraint(); + int count = GetPredicateConstraintLaneCount(vform, pattern); + int multiplier = instr->ExtractBits(19, 16) + 1; + + switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) { + case DECB_r_rs: + case DECD_r_rs: + case DECH_r_rs: + case DECW_r_rs: + count = -count; + break; + case INCB_r_rs: + case INCD_r_rs: + case INCH_r_rs: + case INCW_r_rs: + // Nothing to do. + break; + default: + VIXL_UNIMPLEMENTED(); + return; + } + + WriteXRegister(instr->GetRd(), + IncDecN(ReadXRegister(instr->GetRd()), + count * multiplier, + kXRegSize)); +} + +void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + if (LaneSizeInBitsFromFormat(vform) == kBRegSize) { + VIXL_UNIMPLEMENTED(); + } + + int pattern = instr->GetImmSVEPredicateConstraint(); + int count = GetPredicateConstraintLaneCount(vform, pattern); + int multiplier = instr->ExtractBits(19, 16) + 1; + + switch (instr->Mask(SVEIncDecVectorByElementCountMask)) { + case DECD_z_zs: + case DECH_z_zs: + case DECW_z_zs: + count = -count; + break; + case INCD_z_zs: + case INCH_z_zs: + case INCW_z_zs: + // Nothing to do. + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister scratch; + dup_immediate(vform, + scratch, + IncDecN(0, + count * multiplier, + LaneSizeInBitsFromFormat(vform))); + add(vform, zd, zd, scratch); +} + +void Simulator::VisitSVESaturatingIncDecRegisterByElementCount( + const Instruction* instr) { + // Although the instructions have a separate encoding class, the lane size is + // encoded in the same way as most other SVE instructions. + VectorFormat vform = instr->GetSVEVectorFormat(); + + int pattern = instr->GetImmSVEPredicateConstraint(); + int count = GetPredicateConstraintLaneCount(vform, pattern); + int multiplier = instr->ExtractBits(19, 16) + 1; + + unsigned width = kXRegSize; + bool is_signed = false; + + switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) { + case SQDECB_r_rs_sx: + case SQDECD_r_rs_sx: + case SQDECH_r_rs_sx: + case SQDECW_r_rs_sx: + width = kWRegSize; + VIXL_FALLTHROUGH(); + case SQDECB_r_rs_x: + case SQDECD_r_rs_x: + case SQDECH_r_rs_x: + case SQDECW_r_rs_x: + is_signed = true; + count = -count; + break; + case SQINCB_r_rs_sx: + case SQINCD_r_rs_sx: + case SQINCH_r_rs_sx: + case SQINCW_r_rs_sx: + width = kWRegSize; + VIXL_FALLTHROUGH(); + case SQINCB_r_rs_x: + case SQINCD_r_rs_x: + case SQINCH_r_rs_x: + case SQINCW_r_rs_x: + is_signed = true; + break; + case UQDECB_r_rs_uw: + case UQDECD_r_rs_uw: + case UQDECH_r_rs_uw: + case UQDECW_r_rs_uw: + width = kWRegSize; + VIXL_FALLTHROUGH(); + case UQDECB_r_rs_x: + case UQDECD_r_rs_x: + case UQDECH_r_rs_x: + case UQDECW_r_rs_x: + count = -count; + break; + case UQINCB_r_rs_uw: + case UQINCD_r_rs_uw: + case UQINCH_r_rs_uw: + case UQINCW_r_rs_uw: + width = kWRegSize; + VIXL_FALLTHROUGH(); + case UQINCB_r_rs_x: + case UQINCD_r_rs_x: + case UQINCH_r_rs_x: + case UQINCW_r_rs_x: + // Nothing to do. + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + WriteXRegister(instr->GetRd(), + IncDecN(ReadXRegister(instr->GetRd()), + count * multiplier, + width, + true, + is_signed)); +} + +void Simulator::VisitSVESaturatingIncDecVectorByElementCount( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + if (LaneSizeInBitsFromFormat(vform) == kBRegSize) { + VIXL_UNIMPLEMENTED(); + } + + int pattern = instr->GetImmSVEPredicateConstraint(); + int count = GetPredicateConstraintLaneCount(vform, pattern); + int multiplier = instr->ExtractBits(19, 16) + 1; + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister scratch; + dup_immediate(vform, + scratch, + IncDecN(0, + count * multiplier, + LaneSizeInBitsFromFormat(vform))); + + switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) { + case SQDECD_z_zs: + case SQDECH_z_zs: + case SQDECW_z_zs: + sub(vform, zd, zd, scratch).SignedSaturate(vform); + break; + case SQINCD_z_zs: + case SQINCH_z_zs: + case SQINCW_z_zs: + add(vform, zd, zd, scratch).SignedSaturate(vform); + break; + case UQDECD_z_zs: + case UQDECH_z_zs: + case UQDECW_z_zs: + sub(vform, zd, zd, scratch).UnsignedSaturate(vform); + break; + case UQINCD_z_zs: + case UQINCH_z_zs: + case UQINCW_z_zs: + add(vform, zd, zd, scratch).UnsignedSaturate(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEElementCount(const Instruction* instr) { + switch (instr->Mask(SVEElementCountMask)) { + case CNTB_r_s: + case CNTD_r_s: + case CNTH_r_s: + case CNTW_r_s: + // All handled below. + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + // Although the instructions are separated, the lane size is encoded in the + // same way as most other SVE instructions. + VectorFormat vform = instr->GetSVEVectorFormat(); + + int pattern = instr->GetImmSVEPredicateConstraint(); + int count = GetPredicateConstraintLaneCount(vform, pattern); + int multiplier = instr->ExtractBits(19, 16) + 1; + WriteXRegister(instr->GetRd(), count * multiplier); +} + +void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& vdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPAccumulatingReductionMask)) { + case FADDA_v_p_z: + fadda(vform, vdn, pg, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + SimVRegister result; + switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) { + case FABD_z_p_zz: + fabd(vform, result, zdn, zm); + break; + case FADD_z_p_zz: + fadd(vform, result, zdn, zm); + break; + case FDIVR_z_p_zz: + fdiv(vform, result, zm, zdn); + break; + case FDIV_z_p_zz: + fdiv(vform, result, zdn, zm); + break; + case FMAXNM_z_p_zz: + fmaxnm(vform, result, zdn, zm); + break; + case FMAX_z_p_zz: + fmax(vform, result, zdn, zm); + break; + case FMINNM_z_p_zz: + fminnm(vform, result, zdn, zm); + break; + case FMIN_z_p_zz: + fmin(vform, result, zdn, zm); + break; + case FMULX_z_p_zz: + fmulx(vform, result, zdn, zm); + break; + case FMUL_z_p_zz: + fmul(vform, result, zdn, zm); + break; + case FSCALE_z_p_zz: + fscale(vform, result, zdn, zm); + break; + case FSUBR_z_p_zz: + fsub(vform, result, zm, zdn); + break; + case FSUB_z_p_zz: + fsub(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEFPArithmeticWithImm_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + if (LaneSizeInBitsFromFormat(vform) == kBRegSize) { + VIXL_UNIMPLEMENTED(); + } + + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + int i1 = instr->ExtractBit(5); + SimVRegister add_sub_imm, min_max_imm, mul_imm; + uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5); + uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0); + uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0); + dup_immediate(vform, add_sub_imm, i1 ? one : half); + dup_immediate(vform, min_max_imm, i1 ? one : 0); + dup_immediate(vform, mul_imm, i1 ? two : half); + + switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) { + case FADD_z_p_zs: + fadd(vform, result, zdn, add_sub_imm); + break; + case FMAXNM_z_p_zs: + fmaxnm(vform, result, zdn, min_max_imm); + break; + case FMAX_z_p_zs: + fmax(vform, result, zdn, min_max_imm); + break; + case FMINNM_z_p_zs: + fminnm(vform, result, zdn, min_max_imm); + break; + case FMIN_z_p_zs: + fmin(vform, result, zdn, min_max_imm); + break; + case FMUL_z_p_zs: + fmul(vform, result, zdn, mul_imm); + break; + case FSUBR_z_p_zs: + fsub(vform, result, add_sub_imm, zdn); + break; + case FSUB_z_p_zs: + fsub(vform, result, zdn, add_sub_imm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) { + case FTMAD_z_zzi: + ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16)); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) { + case FADD_z_zz: + fadd(vform, zd, zn, zm); + break; + case FMUL_z_zz: + fmul(vform, zd, zn, zm); + break; + case FRECPS_z_zz: + frecps(vform, zd, zn, zm); + break; + case FRSQRTS_z_zz: + frsqrts(vform, zd, zn, zm); + break; + case FSUB_z_zz: + fsub(vform, zd, zn, zm); + break; + case FTSMUL_z_zz: + ftsmul(vform, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) { + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister result; + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPCompareVectorsMask)) { + case FACGE_p_p_zz: + fabscmp(vform, result, zn, zm, ge); + break; + case FACGT_p_p_zz: + fabscmp(vform, result, zn, zm, gt); + break; + case FCMEQ_p_p_zz: + fcmp(vform, result, zn, zm, eq); + break; + case FCMGE_p_p_zz: + fcmp(vform, result, zn, zm, ge); + break; + case FCMGT_p_p_zz: + fcmp(vform, result, zn, zm, gt); + break; + case FCMNE_p_p_zz: + fcmp(vform, result, zn, zm, ne); + break; + case FCMUO_p_p_zz: + fcmp(vform, result, zn, zm, uo); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + ExtractFromSimVRegister(vform, pd, result); + mov_zeroing(pd, pg, pd); +} + +void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) { + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = instr->GetSVEVectorFormat(); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + SimVRegister result; + SimVRegister zeros; + dup_immediate(kFormatVnD, zeros, 0); + + switch (instr->Mask(SVEFPCompareWithZeroMask)) { + case FCMEQ_p_p_z0: + fcmp(vform, result, zn, zeros, eq); + break; + case FCMGE_p_p_z0: + fcmp(vform, result, zn, zeros, ge); + break; + case FCMGT_p_p_z0: + fcmp(vform, result, zn, zeros, gt); + break; + case FCMLE_p_p_z0: + fcmp(vform, result, zn, zeros, le); + break; + case FCMLT_p_p_z0: + fcmp(vform, result, zn, zeros, lt); + break; + case FCMNE_p_p_z0: + fcmp(vform, result, zn, zeros, ne); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + ExtractFromSimVRegister(vform, pd, result); + mov_zeroing(pd, pg, pd); +} + +void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + + if (LaneSizeInBitsFromFormat(vform) == kBRegSize) { + VIXL_UNIMPLEMENTED(); + } + + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + int rot = instr->ExtractBit(16); + + SimVRegister result; + + switch (instr->Mask(SVEFPComplexAdditionMask)) { + case FCADD_z_p_zz: + fcadd(vform, result, zdn, zm, rot); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + + if (LaneSizeInBitsFromFormat(vform) == kBRegSize) { + VIXL_UNIMPLEMENTED(); + } + + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + int rot = instr->ExtractBits(14, 13); + + SimVRegister result; + + switch (instr->Mask(SVEFPComplexMulAddMask)) { + case FCMLA_z_p_zzz: + fcmla(vform, result, zn, zm, zda, rot); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zda, pg, result); +} + +void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) { + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + int rot = instr->ExtractBits(11, 10); + unsigned zm_code = instr->GetRm(); + int index = -1; + VectorFormat vform, vform_dup; + + switch (instr->Mask(SVEFPComplexMulAddIndexMask)) { + case FCMLA_z_zzzi_h: + vform = kFormatVnH; + vform_dup = kFormatVnS; + index = zm_code >> 3; + zm_code &= 0x7; + break; + case FCMLA_z_zzzi_s: + vform = kFormatVnS; + vform_dup = kFormatVnD; + index = zm_code >> 4; + zm_code &= 0xf; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (index >= 0) { + SimVRegister temp; + dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index); + fcmla(vform, zda, zn, temp, zda, rot); + } +} + +typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform, + LogicVRegister dst, + const LogicVRegister& src); + +void Simulator::VisitSVEFPFastReduction(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& vd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + int lane_size = LaneSizeInBitsFromFormat(vform); + + uint64_t inactive_value = 0; + FastReduceFn fn = nullptr; + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPFastReductionMask)) { + case FADDV_v_p_z: + fn = &Simulator::faddv; + break; + case FMAXNMV_v_p_z: + inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN); + fn = &Simulator::fmaxnmv; + break; + case FMAXV_v_p_z: + inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity); + fn = &Simulator::fmaxv; + break; + case FMINNMV_v_p_z: + inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN); + fn = &Simulator::fminnmv; + break; + case FMINV_v_p_z: + inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity); + fn = &Simulator::fminv; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister scratch; + dup_immediate(vform, scratch, inactive_value); + mov_merging(vform, scratch, pg, zn); + if (fn != nullptr) (this->*fn)(vform, vd, scratch); +} + +void Simulator::VisitSVEFPMulIndex(const Instruction* instr) { + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEFPMulIndexMask)) { + case FMUL_z_zzi_d: + vform = kFormatVnD; + break; + case FMUL_z_zzi_h_i3h: + case FMUL_z_zzi_h: + vform = kFormatVnH; + break; + case FMUL_z_zzi_s: + vform = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister temp; + + dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex()); + fmul(vform, zd, zn, temp); +} + +void Simulator::VisitSVEFPMulAdd(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + if (instr->ExtractBit(15) == 0) { + // Floating-point multiply-accumulate writing addend. + SimVRegister& zm = ReadVRegister(instr->GetRm()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + switch (instr->Mask(SVEFPMulAddMask)) { + // zda = zda + zn * zm + case FMLA_z_p_zzz: + fmla(vform, result, zd, zn, zm); + break; + // zda = -zda + -zn * zm + case FNMLA_z_p_zzz: + fneg(vform, result, zd); + fmls(vform, result, result, zn, zm); + break; + // zda = zda + -zn * zm + case FMLS_z_p_zzz: + fmls(vform, result, zd, zn, zm); + break; + // zda = -zda + zn * zm + case FNMLS_z_p_zzz: + fneg(vform, result, zd); + fmla(vform, result, result, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } else { + // Floating-point multiply-accumulate writing multiplicand. + SimVRegister& za = ReadVRegister(instr->GetRm()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + + switch (instr->Mask(SVEFPMulAddMask)) { + // zdn = za + zdn * zm + case FMAD_z_p_zzz: + fmla(vform, result, za, zd, zm); + break; + // zdn = -za + -zdn * zm + case FNMAD_z_p_zzz: + fneg(vform, result, za); + fmls(vform, result, result, zd, zm); + break; + // zdn = za + -zdn * zm + case FMSB_z_p_zzz: + fmls(vform, result, za, zd, zm); + break; + // zdn = -za + zdn * zm + case FNMSB_z_p_zzz: + fneg(vform, result, za); + fmla(vform, result, result, zd, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } + + mov_merging(vform, zd, pg, result); +} + +void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) { + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEFPMulAddIndexMask)) { + case FMLA_z_zzzi_d: + case FMLS_z_zzzi_d: + vform = kFormatVnD; + break; + case FMLA_z_zzzi_s: + case FMLS_z_zzzi_s: + vform = kFormatVnS; + break; + case FMLA_z_zzzi_h: + case FMLS_z_zzzi_h: + case FMLA_z_zzzi_h_i3h: + case FMLS_z_zzzi_h_i3h: + vform = kFormatVnH; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister temp; + + dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex()); + if (instr->ExtractBit(10) == 1) { + fmls(vform, zd, zd, zn, temp); + } else { + fmla(vform, zd, zd, zn, temp); + } +} + +void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + int dst_data_size; + int src_data_size; + + switch (instr->Mask(SVEFPConvertToIntMask)) { + case FCVTZS_z_p_z_d2w: + case FCVTZU_z_p_z_d2w: + dst_data_size = kSRegSize; + src_data_size = kDRegSize; + break; + case FCVTZS_z_p_z_d2x: + case FCVTZU_z_p_z_d2x: + dst_data_size = kDRegSize; + src_data_size = kDRegSize; + break; + case FCVTZS_z_p_z_fp162h: + case FCVTZU_z_p_z_fp162h: + dst_data_size = kHRegSize; + src_data_size = kHRegSize; + break; + case FCVTZS_z_p_z_fp162w: + case FCVTZU_z_p_z_fp162w: + dst_data_size = kSRegSize; + src_data_size = kHRegSize; + break; + case FCVTZS_z_p_z_fp162x: + case FCVTZU_z_p_z_fp162x: + dst_data_size = kDRegSize; + src_data_size = kHRegSize; + break; + case FCVTZS_z_p_z_s2w: + case FCVTZU_z_p_z_s2w: + dst_data_size = kSRegSize; + src_data_size = kSRegSize; + break; + case FCVTZS_z_p_z_s2x: + case FCVTZU_z_p_z_s2x: + dst_data_size = kDRegSize; + src_data_size = kSRegSize; + break; + default: + VIXL_UNIMPLEMENTED(); + dst_data_size = 0; + src_data_size = 0; + break; + } + + VectorFormat vform = + SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size)); + + if (instr->ExtractBit(16) == 0) { + fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero); + } else { + fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero); + } +} + +void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat dst_data_size = kFormatUndefined; + VectorFormat src_data_size = kFormatUndefined; + + switch (instr->Mask(SVEFPConvertPrecisionMask)) { + case FCVT_z_p_z_d2h: + dst_data_size = kFormatVnH; + src_data_size = kFormatVnD; + break; + case FCVT_z_p_z_d2s: + dst_data_size = kFormatVnS; + src_data_size = kFormatVnD; + break; + case FCVT_z_p_z_h2d: + dst_data_size = kFormatVnD; + src_data_size = kFormatVnH; + break; + case FCVT_z_p_z_h2s: + dst_data_size = kFormatVnS; + src_data_size = kFormatVnH; + break; + case FCVT_z_p_z_s2d: + dst_data_size = kFormatVnD; + src_data_size = kFormatVnS; + break; + case FCVT_z_p_z_s2h: + dst_data_size = kFormatVnH; + src_data_size = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + fcvt(dst_data_size, src_data_size, zd, pg, zn); +} + +void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister result; + + switch (instr->Mask(SVEFPUnaryOpMask)) { + case FRECPX_z_p_z: + frecpx(vform, result, zn); + break; + case FSQRT_z_p_z: + fsqrt(vform, result, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zd, pg, result); +} + +void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = instr->GetSVEVectorFormat(); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + bool exact_exception = false; + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPRoundToIntegralValueMask)) { + case FRINTA_z_p_z: + fpcr_rounding = FPTieAway; + break; + case FRINTI_z_p_z: + break; // Use FPCR rounding mode. + case FRINTM_z_p_z: + fpcr_rounding = FPNegativeInfinity; + break; + case FRINTN_z_p_z: + fpcr_rounding = FPTieEven; + break; + case FRINTP_z_p_z: + fpcr_rounding = FPPositiveInfinity; + break; + case FRINTX_z_p_z: + exact_exception = true; + break; + case FRINTZ_z_p_z: + fpcr_rounding = FPZero; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister result; + frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger); + mov_merging(vform, zd, pg, result); +} + +void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + int dst_data_size; + int src_data_size; + + switch (instr->Mask(SVEIntConvertToFPMask)) { + case SCVTF_z_p_z_h2fp16: + case UCVTF_z_p_z_h2fp16: + dst_data_size = kHRegSize; + src_data_size = kHRegSize; + break; + case SCVTF_z_p_z_w2d: + case UCVTF_z_p_z_w2d: + dst_data_size = kDRegSize; + src_data_size = kSRegSize; + break; + case SCVTF_z_p_z_w2fp16: + case UCVTF_z_p_z_w2fp16: + dst_data_size = kHRegSize; + src_data_size = kSRegSize; + break; + case SCVTF_z_p_z_w2s: + case UCVTF_z_p_z_w2s: + dst_data_size = kSRegSize; + src_data_size = kSRegSize; + break; + case SCVTF_z_p_z_x2d: + case UCVTF_z_p_z_x2d: + dst_data_size = kDRegSize; + src_data_size = kDRegSize; + break; + case SCVTF_z_p_z_x2fp16: + case UCVTF_z_p_z_x2fp16: + dst_data_size = kHRegSize; + src_data_size = kDRegSize; + break; + case SCVTF_z_p_z_x2s: + case UCVTF_z_p_z_x2s: + dst_data_size = kSRegSize; + src_data_size = kDRegSize; + break; + default: + VIXL_UNIMPLEMENTED(); + dst_data_size = 0; + src_data_size = 0; + break; + } + + VectorFormat vform = + SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size)); + + if (instr->ExtractBit(16) == 0) { + scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding); + } else { + ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding); + } +} + +void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + FPRounding fpcr_rounding = static_cast(ReadFpcr().GetRMode()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) { + case FRECPE_z_z: + frecpe(vform, zd, zn, fpcr_rounding); + break; + case FRSQRTE_z_z: + frsqrte(vform, zd, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5)); + + int count = CountActiveLanes(vform, pg); + + if (instr->ExtractBit(11) == 0) { + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + switch (instr->Mask(SVEIncDecByPredicateCountMask)) { + case DECP_z_p_z: + sub_uint(vform, zdn, zdn, count); + break; + case INCP_z_p_z: + add_uint(vform, zdn, zdn, count); + break; + case SQDECP_z_p_z: + sub_uint(vform, zdn, zdn, count).SignedSaturate(vform); + break; + case SQINCP_z_p_z: + add_uint(vform, zdn, zdn, count).SignedSaturate(vform); + break; + case UQDECP_z_p_z: + sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform); + break; + case UQINCP_z_p_z: + add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } else { + bool is_saturating = (instr->ExtractBit(18) == 0); + bool decrement = + is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16); + bool is_signed = (instr->ExtractBit(16) == 0); + bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true; + unsigned width = sf ? kXRegSize : kWRegSize; + + switch (instr->Mask(SVEIncDecByPredicateCountMask)) { + case DECP_r_p_r: + case INCP_r_p_r: + case SQDECP_r_p_r_sx: + case SQDECP_r_p_r_x: + case SQINCP_r_p_r_sx: + case SQINCP_r_p_r_x: + case UQDECP_r_p_r_uw: + case UQDECP_r_p_r_x: + case UQINCP_r_p_r_uw: + case UQINCP_r_p_r_x: + WriteXRegister(instr->GetRd(), + IncDecN(ReadXRegister(instr->GetRd()), + decrement ? -count : count, + width, + is_saturating, + is_signed)); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } +} + +uint64_t Simulator::IncDecN(uint64_t acc, + int64_t delta, + unsigned n, + bool is_saturating, + bool is_signed) { + VIXL_ASSERT(n <= 64); + VIXL_ASSERT(IsIntN(n, delta)); + + uint64_t sign_mask = UINT64_C(1) << (n - 1); + uint64_t mask = GetUintMask(n); + + acc &= mask; // Ignore initial accumulator high bits. + uint64_t result = (acc + delta) & mask; + + bool result_negative = ((result & sign_mask) != 0); + + if (is_saturating) { + if (is_signed) { + bool acc_negative = ((acc & sign_mask) != 0); + bool delta_negative = delta < 0; + + // If the signs of the operands are the same, but different from the + // result, there was an overflow. + if ((acc_negative == delta_negative) && + (acc_negative != result_negative)) { + if (result_negative) { + // Saturate to [..., INT_MAX]. + result_negative = false; + result = mask & ~sign_mask; // E.g. 0x000000007fffffff + } else { + // Saturate to [INT_MIN, ...]. + result_negative = true; + result = ~mask | sign_mask; // E.g. 0xffffffff80000000 + } + } + } else { + if ((delta < 0) && (result > acc)) { + // Saturate to [0, ...]. + result = 0; + } else if ((delta > 0) && (result < acc)) { + // Saturate to [..., UINT_MAX]. + result = mask; + } + } + } + + // Sign-extend if necessary. + if (result_negative && is_signed) result |= ~mask; + + return result; +} + +void Simulator::VisitSVEIndexGeneration(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + switch (instr->Mask(SVEIndexGenerationMask)) { + case INDEX_z_ii: + case INDEX_z_ir: + case INDEX_z_ri: + case INDEX_z_rr: { + uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn()) + : instr->ExtractSignedBits(9, 5); + uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm()) + : instr->ExtractSignedBits(20, 16); + index(vform, zd, start, step); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) { + case ADD_z_zz: + add(vform, zd, zn, zm); + break; + case SQADD_z_zz: + add(vform, zd, zn, zm).SignedSaturate(vform); + break; + case SQSUB_z_zz: + sub(vform, zd, zn, zm).SignedSaturate(vform); + break; + case SUB_z_zz: + sub(vform, zd, zn, zm); + break; + case UQADD_z_zz: + add(vform, zd, zn, zm).UnsignedSaturate(vform); + break; + case UQSUB_z_zz: + sub(vform, zd, zn, zm).UnsignedSaturate(vform); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntAddSubtractVectors_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) { + case ADD_z_p_zz: + add(vform, result, zdn, zm); + break; + case SUBR_z_p_zz: + sub(vform, result, zm, zdn); + break; + case SUB_z_p_zz: + sub(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) { + case AND_z_p_zz: + SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm); + break; + case BIC_z_p_zz: + SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm); + break; + case EOR_z_p_zz: + SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm); + break; + case ORR_z_p_zz: + SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) { + case MUL_z_p_zz: + mul(vform, result, zdn, zm); + break; + case SMULH_z_p_zz: + smulh(vform, result, zdn, zm); + break; + case UMULH_z_p_zz: + umulh(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEIntMinMaxDifference_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) { + case SABD_z_p_zz: + absdiff(vform, result, zdn, zm, true); + break; + case SMAX_z_p_zz: + smax(vform, result, zdn, zm); + break; + case SMIN_z_p_zz: + smin(vform, result, zdn, zm); + break; + case UABD_z_p_zz: + absdiff(vform, result, zdn, zm, false); + break; + case UMAX_z_p_zz: + umax(vform, result, zdn, zm); + break; + case UMIN_z_p_zz: + umin(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister scratch; + + switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) { + case MUL_z_zi: + dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned()); + mul(vform, zd, zd, scratch); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD)); + + switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) { + case SDIVR_z_p_zz: + sdiv(vform, result, zm, zdn); + break; + case SDIV_z_p_zz: + sdiv(vform, result, zdn, zm); + break; + case UDIVR_z_p_zz: + udiv(vform, result, zm, zdn); + break; + case UDIV_z_p_zz: + udiv(vform, result, zdn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zdn, pg, result); +} + +void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister scratch; + + uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned(); + int64_t signed_imm = instr->GetImmSVEIntWideSigned(); + + switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) { + case SMAX_z_zi: + dup_immediate(vform, scratch, signed_imm); + smax(vform, zd, zd, scratch); + break; + case SMIN_z_zi: + dup_immediate(vform, scratch, signed_imm); + smin(vform, zd, zd, scratch); + break; + case UMAX_z_zi: + dup_immediate(vform, scratch, unsigned_imm); + umax(vform, zd, zd, scratch); + break; + case UMIN_z_zi: + dup_immediate(vform, scratch, unsigned_imm); + umin(vform, zd, zd, scratch); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntCompareScalarCountAndLimit( + const Instruction* instr) { + unsigned rn_code = instr->GetRn(); + unsigned rm_code = instr->GetRm(); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + + bool is_64_bit = instr->ExtractBit(12) == 1; + int rsize = is_64_bit ? kXRegSize : kWRegSize; + uint64_t mask = is_64_bit ? kXRegMask : kWRegMask; + + uint64_t usrc1 = ReadXRegister(rn_code); + int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code); + uint64_t usrc2 = ssrc2 & mask; + + bool reverse = (form_hash_ == "whilege_p_p_rr"_h) || + (form_hash_ == "whilegt_p_p_rr"_h) || + (form_hash_ == "whilehi_p_p_rr"_h) || + (form_hash_ == "whilehs_p_p_rr"_h); + + int lane_count = LaneCountFromFormat(vform); + bool last = true; + for (int i = 0; i < lane_count; i++) { + usrc1 &= mask; + int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1); + + bool cond = false; + switch (form_hash_) { + case "whilele_p_p_rr"_h: + cond = ssrc1 <= ssrc2; + break; + case "whilelo_p_p_rr"_h: + cond = usrc1 < usrc2; + break; + case "whilels_p_p_rr"_h: + cond = usrc1 <= usrc2; + break; + case "whilelt_p_p_rr"_h: + cond = ssrc1 < ssrc2; + break; + case "whilege_p_p_rr"_h: + cond = ssrc1 >= ssrc2; + break; + case "whilegt_p_p_rr"_h: + cond = ssrc1 > ssrc2; + break; + case "whilehi_p_p_rr"_h: + cond = usrc1 > usrc2; + break; + case "whilehs_p_p_rr"_h: + cond = usrc1 >= usrc2; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + last = last && cond; + LogicPRegister dst(pd); + int lane = reverse ? ((lane_count - 1) - i) : i; + dst.SetActive(vform, lane, last); + usrc1 += reverse ? -1 : 1; + } + + PredTest(vform, GetPTrue(), pd); + LogSystemRegister(NZCV); +} + +void Simulator::VisitSVEConditionallyTerminateScalars( + const Instruction* instr) { + unsigned rn_code = instr->GetRn(); + unsigned rm_code = instr->GetRm(); + bool is_64_bit = instr->ExtractBit(22) == 1; + uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code); + uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code); + bool term = false; + switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) { + case CTERMEQ_rr: + term = src1 == src2; + break; + case CTERMNE_rr: + term = src1 != src2; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + ReadNzcv().SetN(term ? 1 : 0); + ReadNzcv().SetV(term ? 0 : !ReadC()); + LogSystemRegister(NZCV); +} + +void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) { + bool commute_inputs = false; + Condition cond = al; + switch (instr->Mask(SVEIntCompareSignedImmMask)) { + case CMPEQ_p_p_zi: + cond = eq; + break; + case CMPGE_p_p_zi: + cond = ge; + break; + case CMPGT_p_p_zi: + cond = gt; + break; + case CMPLE_p_p_zi: + cond = ge; + commute_inputs = true; + break; + case CMPLT_p_p_zi: + cond = gt; + commute_inputs = true; + break; + case CMPNE_p_p_zi: + cond = ne; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister src2; + dup_immediate(vform, + src2, + ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16))); + SVEIntCompareVectorsHelper(cond, + vform, + ReadPRegister(instr->GetPd()), + ReadPRegister(instr->GetPgLow8()), + commute_inputs ? src2 + : ReadVRegister(instr->GetRn()), + commute_inputs ? ReadVRegister(instr->GetRn()) + : src2); +} + +void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) { + bool commute_inputs = false; + Condition cond = al; + switch (instr->Mask(SVEIntCompareUnsignedImmMask)) { + case CMPHI_p_p_zi: + cond = hi; + break; + case CMPHS_p_p_zi: + cond = hs; + break; + case CMPLO_p_p_zi: + cond = hi; + commute_inputs = true; + break; + case CMPLS_p_p_zi: + cond = hs; + commute_inputs = true; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister src2; + dup_immediate(vform, src2, instr->ExtractBits(20, 14)); + SVEIntCompareVectorsHelper(cond, + vform, + ReadPRegister(instr->GetPd()), + ReadPRegister(instr->GetPgLow8()), + commute_inputs ? src2 + : ReadVRegister(instr->GetRn()), + commute_inputs ? ReadVRegister(instr->GetRn()) + : src2); +} + +void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) { + Instr op = instr->Mask(SVEIntCompareVectorsMask); + bool is_wide_elements = false; + switch (op) { + case CMPEQ_p_p_zw: + case CMPGE_p_p_zw: + case CMPGT_p_p_zw: + case CMPHI_p_p_zw: + case CMPHS_p_p_zw: + case CMPLE_p_p_zw: + case CMPLO_p_p_zw: + case CMPLS_p_p_zw: + case CMPLT_p_p_zw: + case CMPNE_p_p_zw: + is_wide_elements = true; + break; + } + + Condition cond; + switch (op) { + case CMPEQ_p_p_zw: + case CMPEQ_p_p_zz: + cond = eq; + break; + case CMPGE_p_p_zw: + case CMPGE_p_p_zz: + cond = ge; + break; + case CMPGT_p_p_zw: + case CMPGT_p_p_zz: + cond = gt; + break; + case CMPHI_p_p_zw: + case CMPHI_p_p_zz: + cond = hi; + break; + case CMPHS_p_p_zw: + case CMPHS_p_p_zz: + cond = hs; + break; + case CMPNE_p_p_zw: + case CMPNE_p_p_zz: + cond = ne; + break; + case CMPLE_p_p_zw: + cond = le; + break; + case CMPLO_p_p_zw: + cond = lo; + break; + case CMPLS_p_p_zw: + cond = ls; + break; + case CMPLT_p_p_zw: + cond = lt; + break; + default: + VIXL_UNIMPLEMENTED(); + cond = al; + break; + } + + SVEIntCompareVectorsHelper(cond, + instr->GetSVEVectorFormat(), + ReadPRegister(instr->GetPd()), + ReadPRegister(instr->GetPgLow8()), + ReadVRegister(instr->GetRn()), + ReadVRegister(instr->GetRm()), + is_wide_elements); +} + +void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) || + (vform == kFormatVnD)); + + switch (instr->Mask(SVEFPExponentialAcceleratorMask)) { + case FEXPA_z_z: + fexpa(vform, zd, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) || + (vform == kFormatVnD)); + + switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) { + case FTSSEL_z_zz: + ftssel(vform, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEConstructivePrefix_Unpredicated( + const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) { + case MOVPRFX_z_z: + mov(kFormatVnD, zd, zn); // The lane size is arbitrary. + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + SimVRegister result; + switch (instr->Mask(SVEIntMulAddPredicatedMask)) { + case MLA_z_p_zzz: + mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm); + break; + case MLS_z_p_zzz: + mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm); + break; + case MAD_z_p_zzz: + // 'za' is encoded in 'Rn'. + mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm); + break; + case MSB_z_p_zzz: { + // 'za' is encoded in 'Rn'. + mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result); +} + +void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + switch (form_hash_) { + case "sdot_z_zzz"_h: + sdot(vform, zda, zn, zm); + break; + case "udot_z_zzz"_h: + udot(vform, zda, zn, zm); + break; + case "usdot_z_zzz_s"_h: + usdot(vform, zda, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEMovprfx(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + + switch (instr->Mask(SVEMovprfxMask)) { + case MOVPRFX_z_p_z: + if (instr->ExtractBit(16)) { + mov_merging(vform, zd, pg, zn); + } else { + mov_zeroing(vform, zd, pg, zn); + } + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEIntReduction(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& vd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) { + switch (instr->Mask(SVEIntReductionLogicalMask)) { + case ANDV_r_p_z: + andv(vform, vd, pg, zn); + break; + case EORV_r_p_z: + eorv(vform, vd, pg, zn); + break; + case ORV_r_p_z: + orv(vform, vd, pg, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } else { + switch (instr->Mask(SVEIntReductionMask)) { + case SADDV_r_p_z: + saddv(vform, vd, pg, zn); + break; + case SMAXV_r_p_z: + smaxv(vform, vd, pg, zn); + break; + case SMINV_r_p_z: + sminv(vform, vd, pg, zn); + break; + case UADDV_r_p_z: + uaddv(vform, vd, pg, zn); + break; + case UMAXV_r_p_z: + umaxv(vform, vd, pg, zn); + break; + case UMINV_r_p_z: + uminv(vform, vd, pg, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + } +} + +void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + + SimVRegister result; + switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) { + case ABS_z_p_z: + abs(vform, result, zn); + break; + case CLS_z_p_z: + cls(vform, result, zn); + break; + case CLZ_z_p_z: + clz(vform, result, zn); + break; + case CNOT_z_p_z: + cnot(vform, result, zn); + break; + case CNT_z_p_z: + cnt(vform, result, zn); + break; + case FABS_z_p_z: + fabs_(vform, result, zn); + break; + case FNEG_z_p_z: + fneg(vform, result, zn); + break; + case NEG_z_p_z: + neg(vform, result, zn); + break; + case NOT_z_p_z: + not_(vform, result, zn); + break; + case SXTB_z_p_z: + case SXTH_z_p_z: + case SXTW_z_p_z: + sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17))); + break; + case UXTB_z_p_z: + case UXTH_z_p_z: + case UXTW_z_p_z: + uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17))); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + mov_merging(vform, zd, pg, result); +} + +void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) { + // There is only one instruction in this group. + VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i); + + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16)); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + + if (vform == kFormatVnB) VIXL_UNIMPLEMENTED(); + + SimVRegister result; + switch (instr->Mask(SVECopyFPImm_PredicatedMask)) { + case FCPY_z_p_i: { + int imm8 = instr->ExtractBits(12, 5); + uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), + Instruction::Imm8ToFP64(imm8)); + dup_immediate(vform, result, value); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } + mov_merging(vform, zd, pg, result); +} + +void Simulator::VisitSVEIntAddSubtractImm_Unpredicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister scratch; + + uint64_t imm = instr->GetImmSVEIntWideUnsigned(); + imm <<= instr->ExtractBit(13) * 8; + + switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) { + case ADD_z_zi: + add_uint(vform, zd, zd, imm); + break; + case SQADD_z_zi: + add_uint(vform, zd, zd, imm).SignedSaturate(vform); + break; + case SQSUB_z_zi: + sub_uint(vform, zd, zd, imm).SignedSaturate(vform); + break; + case SUBR_z_zi: + dup_immediate(vform, scratch, imm); + sub(vform, zd, scratch, zd); + break; + case SUB_z_zi: + sub_uint(vform, zd, zd, imm); + break; + case UQADD_z_zi: + add_uint(vform, zd, zd, imm).UnsignedSaturate(vform); + break; + case UQSUB_z_zi: + sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform); + break; + default: + break; + } +} + +void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + + VectorFormat format = instr->GetSVEVectorFormat(); + int64_t imm = instr->GetImmSVEIntWideSigned(); + int shift = instr->ExtractBit(13) * 8; + imm *= uint64_t{1} << shift; + + switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) { + case DUP_z_i: + // The encoding of byte-sized lanes with lsl #8 is undefined. + if ((format == kFormatVnB) && (shift == 8)) { + VIXL_UNIMPLEMENTED(); + } else { + dup_immediate(format, zd, imm); + } + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + + switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) { + case FDUP_z_i: + switch (vform) { + case kFormatVnH: + dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16())); + break; + case kFormatVnS: + dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32())); + break; + case kFormatVnD: + dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64())); + break; + default: + VIXL_UNIMPLEMENTED(); + } + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) { + case LD1H_z_p_bz_s_x32_scaled: + case LD1SH_z_p_bz_s_x32_scaled: + case LDFF1H_z_p_bz_s_x32_scaled: + case LDFF1SH_z_p_bz_s_x32_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW; + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod); +} + +void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets( + const Instruction* instr) { + switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) { + case LD1B_z_p_bz_s_x32_unscaled: + case LD1H_z_p_bz_s_x32_unscaled: + case LD1SB_z_p_bz_s_x32_unscaled: + case LD1SH_z_p_bz_s_x32_unscaled: + case LD1W_z_p_bz_s_x32_unscaled: + case LDFF1B_z_p_bz_s_x32_unscaled: + case LDFF1H_z_p_bz_s_x32_unscaled: + case LDFF1SB_z_p_bz_s_x32_unscaled: + case LDFF1SH_z_p_bz_s_x32_unscaled: + case LDFF1W_z_p_bz_s_x32_unscaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW; + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod); +} + +void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) { + case LD1B_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LD1H_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LD1SB_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LD1SH_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LD1W_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LDFF1B_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LDFF1H_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LDFF1SB_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LDFF1SH_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + case LDFF1W_z_p_ai_s: + VIXL_UNIMPLEMENTED(); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets( + const Instruction* instr) { + switch ( + instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) { + case LD1W_z_p_bz_s_x32_scaled: + case LDFF1W_z_p_bz_s_x32_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW; + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod); +} + +void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets( + const Instruction* instr) { + switch ( + instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_bz_s_x32_scaled: + case PRFD_i_p_bz_s_x32_scaled: + case PRFH_i_p_bz_s_x32_scaled: + case PRFW_i_p_bz_s_x32_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_ai_s: + case PRFD_i_p_ai_s: + case PRFH_i_p_ai_s: + case PRFW_i_p_ai_s: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_bi_s: + case PRFD_i_p_bi_s: + case PRFH_i_p_bi_s: + case PRFW_i_p_bi_s: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar( + const Instruction* instr) { + switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_br_s: + case PRFD_i_p_br_s: + case PRFH_i_p_br_s: + case PRFW_i_p_br_s: + if (instr->GetRm() == kZeroRegCode) { + VIXL_UNIMPLEMENTED(); + } + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) { + bool is_signed; + switch (instr->Mask(SVELoadAndBroadcastElementMask)) { + case LD1RB_z_p_bi_u8: + case LD1RB_z_p_bi_u16: + case LD1RB_z_p_bi_u32: + case LD1RB_z_p_bi_u64: + case LD1RH_z_p_bi_u16: + case LD1RH_z_p_bi_u32: + case LD1RH_z_p_bi_u64: + case LD1RW_z_p_bi_u32: + case LD1RW_z_p_bi_u64: + case LD1RD_z_p_bi_u64: + is_signed = false; + break; + case LD1RSB_z_p_bi_s16: + case LD1RSB_z_p_bi_s32: + case LD1RSB_z_p_bi_s64: + case LD1RSH_z_p_bi_s32: + case LD1RSH_z_p_bi_s64: + case LD1RSW_z_p_bi_s64: + is_signed = true; + break; + default: + // This encoding group is complete, so no other values should be possible. + VIXL_UNREACHABLE(); + is_signed = false; + break; + } + + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13); + VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset; + VectorFormat unpack_vform = + SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2); + SimVRegister temp; + if (!ld1r(vform, unpack_vform, temp, base, is_signed)) return; + mov_zeroing(vform, + ReadVRegister(instr->GetRt()), + ReadPRegister(instr->GetPgLow8()), + temp); +} + +void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) { + switch (instr->Mask(SVELoadPredicateRegisterMask)) { + case LDR_p_bi: { + SimPRegister& pt = ReadPRegister(instr->GetPt()); + int pl = GetPredicateLengthInBytes(); + int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10); + uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t address = base + multiplier * pl; + for (int i = 0; i < pl; i++) { + VIXL_DEFINE_OR_RETURN(value, MemRead(address + i)); + pt.Insert(i, value); + } + LogPRead(instr->GetPt(), address); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) { + switch (instr->Mask(SVELoadVectorRegisterMask)) { + case LDR_z_bi: { + SimVRegister& zt = ReadVRegister(instr->GetRt()); + int vl = GetVectorLengthInBytes(); + int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10); + uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t address = base + multiplier * vl; + for (int i = 0; i < vl; i++) { + VIXL_DEFINE_OR_RETURN(value, MemRead(address + i)); + zt.Insert(i, value); + } + LogZRead(instr->GetRt(), address); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) { + case LD1D_z_p_bz_d_x32_scaled: + case LD1H_z_p_bz_d_x32_scaled: + case LD1SH_z_p_bz_d_x32_scaled: + case LD1SW_z_p_bz_d_x32_scaled: + case LD1W_z_p_bz_d_x32_scaled: + case LDFF1H_z_p_bz_d_x32_scaled: + case LDFF1W_z_p_bz_d_x32_scaled: + case LDFF1D_z_p_bz_d_x32_scaled: + case LDFF1SH_z_p_bz_d_x32_scaled: + case LDFF1SW_z_p_bz_d_x32_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW; + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod); +} + +void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) { + case LD1D_z_p_bz_d_64_scaled: + case LD1H_z_p_bz_d_64_scaled: + case LD1SH_z_p_bz_d_64_scaled: + case LD1SW_z_p_bz_d_64_scaled: + case LD1W_z_p_bz_d_64_scaled: + case LDFF1H_z_p_bz_d_64_scaled: + case LDFF1W_z_p_bz_d_64_scaled: + case LDFF1D_z_p_bz_d_64_scaled: + case LDFF1SH_z_p_bz_d_64_scaled: + case LDFF1SW_z_p_bz_d_64_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL); +} + +void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets( + const Instruction* instr) { + switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) { + case LD1B_z_p_bz_d_64_unscaled: + case LD1D_z_p_bz_d_64_unscaled: + case LD1H_z_p_bz_d_64_unscaled: + case LD1SB_z_p_bz_d_64_unscaled: + case LD1SH_z_p_bz_d_64_unscaled: + case LD1SW_z_p_bz_d_64_unscaled: + case LD1W_z_p_bz_d_64_unscaled: + case LDFF1B_z_p_bz_d_64_unscaled: + case LDFF1D_z_p_bz_d_64_unscaled: + case LDFF1H_z_p_bz_d_64_unscaled: + case LDFF1SB_z_p_bz_d_64_unscaled: + case LDFF1SH_z_p_bz_d_64_unscaled: + case LDFF1SW_z_p_bz_d_64_unscaled: + case LDFF1W_z_p_bz_d_64_unscaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEGatherLoadScalarPlusVectorHelper(instr, + kFormatVnD, + NO_SVE_OFFSET_MODIFIER); +} + +void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) { + case LD1B_z_p_bz_d_x32_unscaled: + case LD1D_z_p_bz_d_x32_unscaled: + case LD1H_z_p_bz_d_x32_unscaled: + case LD1SB_z_p_bz_d_x32_unscaled: + case LD1SH_z_p_bz_d_x32_unscaled: + case LD1SW_z_p_bz_d_x32_unscaled: + case LD1W_z_p_bz_d_x32_unscaled: + case LDFF1B_z_p_bz_d_x32_unscaled: + case LDFF1H_z_p_bz_d_x32_unscaled: + case LDFF1W_z_p_bz_d_x32_unscaled: + case LDFF1D_z_p_bz_d_x32_unscaled: + case LDFF1SB_z_p_bz_d_x32_unscaled: + case LDFF1SH_z_p_bz_d_x32_unscaled: + case LDFF1SW_z_p_bz_d_x32_unscaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW; + SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod); +} + +void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) { + case LD1B_z_p_ai_d: + case LD1D_z_p_ai_d: + case LD1H_z_p_ai_d: + case LD1SB_z_p_ai_d: + case LD1SH_z_p_ai_d: + case LD1SW_z_p_ai_d: + case LD1W_z_p_ai_d: + case LDFF1B_z_p_ai_d: + case LDFF1D_z_p_ai_d: + case LDFF1H_z_p_ai_d: + case LDFF1SB_z_p_ai_d: + case LDFF1SH_z_p_ai_d: + case LDFF1SW_z_p_ai_d: + case LDFF1W_z_p_ai_d: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + bool is_signed = instr->ExtractBit(14) == 0; + bool is_ff = instr->ExtractBit(13) == 1; + // Note that these instructions don't use the Dtype encoding. + int msize_in_bytes_log2 = instr->ExtractBits(24, 23); + uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2; + LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + if (is_ff) { + VIXL_UNIMPLEMENTED(); + } else { + SVEStructuredLoadHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + is_signed); + } +} + +void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets( + const Instruction* instr) { + switch ( + instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_bz_d_64_scaled: + case PRFD_i_p_bz_d_64_scaled: + case PRFH_i_p_bz_d_64_scaled: + case PRFW_i_p_bz_d_64_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator:: + VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_bz_d_x32_scaled: + case PRFD_i_p_bz_d_x32_scaled: + case PRFH_i_p_bz_d_x32_scaled: + case PRFW_i_p_bz_d_x32_scaled: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) { + // Ignore prefetch hint instructions. + case PRFB_i_p_ai_d: + case PRFD_i_p_ai_d: + case PRFH_i_p_ai_d: + case PRFW_i_p_ai_d: + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar( + const Instruction* instr) { + bool is_signed; + switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) { + case LDFF1B_z_p_br_u8: + case LDFF1B_z_p_br_u16: + case LDFF1B_z_p_br_u32: + case LDFF1B_z_p_br_u64: + case LDFF1H_z_p_br_u16: + case LDFF1H_z_p_br_u32: + case LDFF1H_z_p_br_u64: + case LDFF1W_z_p_br_u32: + case LDFF1W_z_p_br_u64: + case LDFF1D_z_p_br_u64: + is_signed = false; + break; + case LDFF1SB_z_p_br_s16: + case LDFF1SB_z_p_br_s32: + case LDFF1SB_z_p_br_s64: + case LDFF1SH_z_p_br_s32: + case LDFF1SH_z_p_br_s64: + case LDFF1SW_z_p_br_s64: + is_signed = true; + break; + default: + // This encoding group is complete, so no other values should be possible. + VIXL_UNREACHABLE(); + is_signed = false; + break; + } + + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed); + VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()); + offset <<= msize_in_bytes_log2; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEFaultTolerantLoadHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + kSVEFirstFaultLoad, + is_signed); +} + +void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm( + const Instruction* instr) { + bool is_signed = false; + switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) { + case LDNF1B_z_p_bi_u16: + case LDNF1B_z_p_bi_u32: + case LDNF1B_z_p_bi_u64: + case LDNF1B_z_p_bi_u8: + case LDNF1D_z_p_bi_u64: + case LDNF1H_z_p_bi_u16: + case LDNF1H_z_p_bi_u32: + case LDNF1H_z_p_bi_u64: + case LDNF1W_z_p_bi_u32: + case LDNF1W_z_p_bi_u64: + break; + case LDNF1SB_z_p_bi_s16: + case LDNF1SB_z_p_bi_s32: + case LDNF1SB_z_p_bi_s64: + case LDNF1SH_z_p_bi_s32: + case LDNF1SH_z_p_bi_s64: + case LDNF1SW_z_p_bi_s64: + is_signed = true; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed); + VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + int vl = GetVectorLengthInBytes(); + int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = + (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2); + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEFaultTolerantLoadHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + kSVENonFaultLoad, + is_signed); +} + +void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm( + const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) { + case LDNT1B_z_p_bi_contiguous: + vform = kFormatVnB; + break; + case LDNT1D_z_p_bi_contiguous: + vform = kFormatVnD; + break; + case LDNT1H_z_p_bi_contiguous: + vform = kFormatVnH; + break; + case LDNT1W_z_p_bi_contiguous: + vform = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform); + int vl = GetVectorLengthInBytes(); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = instr->ExtractSignedBits(19, 16) * vl; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredLoadHelper(vform, + pg, + instr->GetRt(), + addr, + /* is_signed = */ false); +} + +void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar( + const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) { + case LDNT1B_z_p_br_contiguous: + vform = kFormatVnB; + break; + case LDNT1D_z_p_br_contiguous: + vform = kFormatVnD; + break; + case LDNT1H_z_p_br_contiguous: + vform = kFormatVnH; + break; + case LDNT1W_z_p_br_contiguous: + vform = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredLoadHelper(vform, + pg, + instr->GetRt(), + addr, + /* is_signed = */ false); +} + +void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm( + const Instruction* instr) { + SimVRegister& zt = ReadVRegister(instr->GetRt()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + uint64_t dwords = 2; + VectorFormat vform_dst = kFormatVnQ; + if ((form_hash_ == "ld1rob_z_p_bi_u8"_h) || + (form_hash_ == "ld1roh_z_p_bi_u16"_h) || + (form_hash_ == "ld1row_z_p_bi_u32"_h) || + (form_hash_ == "ld1rod_z_p_bi_u64"_h)) { + dwords = 4; + vform_dst = kFormatVnO; + } + + uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = + instr->ExtractSignedBits(19, 16) * dwords * kDRegSizeInBytes; + int msz = instr->ExtractBits(24, 23); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz); + + for (unsigned i = 0; i < dwords; i++) { + if (!ld1(kFormatVnD, zt, i, addr + offset + (i * kDRegSizeInBytes))) return; + } + mov_zeroing(vform, zt, pg, zt); + dup_element(vform_dst, zt, zt, 0); +} + +void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar( + const Instruction* instr) { + SimVRegister& zt = ReadVRegister(instr->GetRt()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + uint64_t bytes = 16; + VectorFormat vform_dst = kFormatVnQ; + if ((form_hash_ == "ld1rob_z_p_br_contiguous"_h) || + (form_hash_ == "ld1roh_z_p_br_contiguous"_h) || + (form_hash_ == "ld1row_z_p_br_contiguous"_h) || + (form_hash_ == "ld1rod_z_p_br_contiguous"_h)) { + bytes = 32; + vform_dst = kFormatVnO; + } + + uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()); + int msz = instr->ExtractBits(24, 23); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz); + offset <<= msz; + for (unsigned i = 0; i < bytes; i++) { + if (!ld1(kFormatVnB, zt, i, addr + offset + i)) return; + } + mov_zeroing(vform, zt, pg, zt); + dup_element(vform_dst, zt, zt, 0); +} + +void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) { + case LD2B_z_p_bi_contiguous: + case LD2D_z_p_bi_contiguous: + case LD2H_z_p_bi_contiguous: + case LD2W_z_p_bi_contiguous: + case LD3B_z_p_bi_contiguous: + case LD3D_z_p_bi_contiguous: + case LD3H_z_p_bi_contiguous: + case LD3W_z_p_bi_contiguous: + case LD4B_z_p_bi_contiguous: + case LD4D_z_p_bi_contiguous: + case LD4H_z_p_bi_contiguous: + case LD4W_z_p_bi_contiguous: { + int vl = GetVectorLengthInBytes(); + int msz = instr->ExtractBits(24, 23); + int reg_count = instr->ExtractBits(22, 21) + 1; + uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count; + LogicSVEAddressVector addr( + ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset); + addr.SetMsizeInBytesLog2(msz); + addr.SetRegCount(reg_count); + SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz), + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar( + const Instruction* instr) { + switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) { + case LD2B_z_p_br_contiguous: + case LD2D_z_p_br_contiguous: + case LD2H_z_p_br_contiguous: + case LD2W_z_p_br_contiguous: + case LD3B_z_p_br_contiguous: + case LD3D_z_p_br_contiguous: + case LD3H_z_p_br_contiguous: + case LD3W_z_p_br_contiguous: + case LD4B_z_p_br_contiguous: + case LD4D_z_p_br_contiguous: + case LD4H_z_p_br_contiguous: + case LD4W_z_p_br_contiguous: { + int msz = instr->ExtractBits(24, 23); + uint64_t offset = ReadXRegister(instr->GetRm()) * (uint64_t{1} << msz); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz); + LogicSVEAddressVector addr( + ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset); + addr.SetMsizeInBytesLog2(msz); + addr.SetRegCount(instr->ExtractBits(22, 21) + 1); + SVEStructuredLoadHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + false); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) { + case ST1H_z_p_bz_s_x32_scaled: + case ST1W_z_p_bz_s_x32_scaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + int scale = instr->ExtractBit(21) * msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + SVEOffsetModifier mod = + (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW; + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnS, + mod, + scale); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnS, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets( + const Instruction* instr) { + switch ( + instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) { + case ST1B_z_p_bz_s_x32_unscaled: + case ST1H_z_p_bz_s_x32_unscaled: + case ST1W_z_p_bz_s_x32_unscaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + SVEOffsetModifier mod = + (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW; + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnS, + mod); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnS, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE32BitScatterStore_VectorPlusImm( + const Instruction* instr) { + int msz = 0; + switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) { + case ST1B_z_p_ai_s: + msz = 0; + break; + case ST1H_z_p_ai_s: + msz = 1; + break; + case ST1W_z_p_ai_s: + msz = 2; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + uint64_t imm = instr->ExtractBits(20, 16) << msz; + LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS); + addr.SetMsizeInBytesLog2(msz); + SVEStructuredStoreHelper(kFormatVnS, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); +} + +void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) { + case ST1D_z_p_bz_d_64_scaled: + case ST1H_z_p_bz_d_64_scaled: + case ST1W_z_p_bz_d_64_scaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + int scale = instr->ExtractBit(21) * msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnD, + SVE_LSL, + scale); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets( + const Instruction* instr) { + switch ( + instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) { + case ST1B_z_p_bz_d_64_unscaled: + case ST1D_z_p_bz_d_64_unscaled: + case ST1H_z_p_bz_d_64_unscaled: + case ST1W_z_p_bz_d_64_unscaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnD, + NO_SVE_OFFSET_MODIFIER); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) { + case ST1D_z_p_bz_d_x32_scaled: + case ST1H_z_p_bz_d_x32_scaled: + case ST1W_z_p_bz_d_x32_scaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + int scale = instr->ExtractBit(21) * msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + SVEOffsetModifier mod = + (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW; + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnD, + mod, + scale); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator:: + VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets( + const Instruction* instr) { + switch (instr->Mask( + SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) { + case ST1B_z_p_bz_d_x32_unscaled: + case ST1D_z_p_bz_d_x32_unscaled: + case ST1H_z_p_bz_d_x32_unscaled: + case ST1W_z_p_bz_d_x32_unscaled: { + unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + SVEOffsetModifier mod = + (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW; + LogicSVEAddressVector addr(base, + &ReadVRegister(instr->GetRm()), + kFormatVnD, + mod); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVE64BitScatterStore_VectorPlusImm( + const Instruction* instr) { + int msz = 0; + switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) { + case ST1B_z_p_ai_d: + msz = 0; + break; + case ST1D_z_p_ai_d: + msz = 3; + break; + case ST1H_z_p_ai_d: + msz = 1; + break; + case ST1W_z_p_ai_d: + msz = 2; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + uint64_t imm = instr->ExtractBits(20, 16) << msz; + LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD); + addr.SetMsizeInBytesLog2(msz); + SVEStructuredStoreHelper(kFormatVnD, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); +} + +void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm( + const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) { + case STNT1B_z_p_bi_contiguous: + vform = kFormatVnB; + break; + case STNT1D_z_p_bi_contiguous: + vform = kFormatVnD; + break; + case STNT1H_z_p_bi_contiguous: + vform = kFormatVnH; + break; + case STNT1W_z_p_bi_contiguous: + vform = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform); + int vl = GetVectorLengthInBytes(); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = instr->ExtractSignedBits(19, 16) * vl; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr); +} + +void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar( + const Instruction* instr) { + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + VectorFormat vform = kFormatUndefined; + + switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) { + case STNT1B_z_p_br_contiguous: + vform = kFormatVnB; + break; + case STNT1D_z_p_br_contiguous: + vform = kFormatVnD; + break; + case STNT1H_z_p_br_contiguous: + vform = kFormatVnH; + break; + case STNT1W_z_p_br_contiguous: + vform = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr); +} + +void Simulator::VisitSVEContiguousStore_ScalarPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) { + case ST1B_z_p_bi: + case ST1D_z_p_bi: + case ST1H_z_p_bi: + case ST1W_z_p_bi: { + int vl = GetVectorLengthInBytes(); + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false); + VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2); + int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = + (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2); + VectorFormat vform = + SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredStoreHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEContiguousStore_ScalarPlusScalar( + const Instruction* instr) { + switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) { + case ST1B_z_p_br: + case ST1D_z_p_br: + case ST1H_z_p_br: + case ST1W_z_p_br: { + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()); + offset <<= instr->ExtractBits(24, 23); + VectorFormat vform = + SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21)); + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23)); + SVEStructuredStoreHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister z_result; + + switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) { + case CPY_z_p_v: + dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0); + mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm( + const Instruction* instr) { + switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) { + case ST2B_z_p_bi_contiguous: + case ST2D_z_p_bi_contiguous: + case ST2H_z_p_bi_contiguous: + case ST2W_z_p_bi_contiguous: + case ST3B_z_p_bi_contiguous: + case ST3D_z_p_bi_contiguous: + case ST3H_z_p_bi_contiguous: + case ST3W_z_p_bi_contiguous: + case ST4B_z_p_bi_contiguous: + case ST4D_z_p_bi_contiguous: + case ST4H_z_p_bi_contiguous: + case ST4W_z_p_bi_contiguous: { + int vl = GetVectorLengthInBytes(); + int msz = instr->ExtractBits(24, 23); + int reg_count = instr->ExtractBits(22, 21) + 1; + uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count; + LogicSVEAddressVector addr( + ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset); + addr.SetMsizeInBytesLog2(msz); + addr.SetRegCount(reg_count); + SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz), + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar( + const Instruction* instr) { + switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) { + case ST2B_z_p_br_contiguous: + case ST2D_z_p_br_contiguous: + case ST2H_z_p_br_contiguous: + case ST2W_z_p_br_contiguous: + case ST3B_z_p_br_contiguous: + case ST3D_z_p_br_contiguous: + case ST3H_z_p_br_contiguous: + case ST3W_z_p_br_contiguous: + case ST4B_z_p_br_contiguous: + case ST4D_z_p_br_contiguous: + case ST4H_z_p_br_contiguous: + case ST4W_z_p_br_contiguous: { + int msz = instr->ExtractBits(24, 23); + uint64_t offset = ReadXRegister(instr->GetRm()) * (uint64_t{1} << msz); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz); + LogicSVEAddressVector addr( + ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset); + addr.SetMsizeInBytesLog2(msz); + addr.SetRegCount(instr->ExtractBits(22, 21) + 1); + SVEStructuredStoreHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) { + switch (instr->Mask(SVEStorePredicateRegisterMask)) { + case STR_p_bi: { + SimPRegister& pt = ReadPRegister(instr->GetPt()); + int pl = GetPredicateLengthInBytes(); + int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10); + uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t address = base + multiplier * pl; + for (int i = 0; i < pl; i++) { + if (!MemWrite(address + i, pt.GetLane(i))) return; + } + LogPWrite(instr->GetPt(), address); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) { + switch (instr->Mask(SVEStoreVectorRegisterMask)) { + case STR_z_bi: { + SimVRegister& zt = ReadVRegister(instr->GetRt()); + int vl = GetVectorLengthInBytes(); + int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10); + uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t address = base + multiplier * vl; + for (int i = 0; i < vl; i++) { + if (!MemWrite(address + i, zt.GetLane(i))) return; + } + LogZWrite(instr->GetRt(), address); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEMulIndex(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zda = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + std::pair zm_and_index = instr->GetSVEMulZmAndIndex(); + SimVRegister zm = ReadVRegister(zm_and_index.first); + int index = zm_and_index.second; + + SimVRegister temp; + dup_elements_to_segments(vform, temp, zm, index); + + switch (form_hash_) { + case "sdot_z_zzzi_d"_h: + case "sdot_z_zzzi_s"_h: + sdot(vform, zda, zn, temp); + break; + case "udot_z_zzzi_d"_h: + case "udot_z_zzzi_s"_h: + udot(vform, zda, zn, temp); + break; + case "sudot_z_zzzi_s"_h: + usdot(vform, zda, temp, zn); + break; + case "usdot_z_zzzi_s"_h: + usdot(vform, zda, zn, temp); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::SimulateMatrixMul(const Instruction* instr) { + VectorFormat vform = kFormatVnS; + SimVRegister& dn = ReadVRegister(instr->GetRd()); + SimVRegister& n = ReadVRegister(instr->GetRn()); + SimVRegister& m = ReadVRegister(instr->GetRm()); + + bool n_signed = false; + bool m_signed = false; + switch (form_hash_) { + case "smmla_asimdsame2_g"_h: + vform = kFormat4S; + VIXL_FALLTHROUGH(); + case "smmla_z_zzz"_h: + n_signed = m_signed = true; + break; + case "ummla_asimdsame2_g"_h: + vform = kFormat4S; + VIXL_FALLTHROUGH(); + case "ummla_z_zzz"_h: + // Nothing to do. + break; + case "usmmla_asimdsame2_g"_h: + vform = kFormat4S; + VIXL_FALLTHROUGH(); + case "usmmla_z_zzz"_h: + m_signed = true; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + matmul(vform, dn, n, m, n_signed, m_signed); +} + +void Simulator::SimulateSVEFPMatrixMul(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + switch (form_hash_) { + case "fmmla_z_zzz_d"_h: + if (GetVectorLengthInBits() < 256) VisitUnimplemented(instr); + VIXL_FALLTHROUGH(); + case "fmmla_z_zzz_s"_h: + fmatmul(vform, zdn, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) { + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + SimPRegister result; + + switch (instr->Mask(SVEPartitionBreakConditionMask)) { + case BRKAS_p_p_p_z: + case BRKA_p_p_p: + brka(result, pg, pn); + break; + case BRKBS_p_p_p_z: + case BRKB_p_p_p: + brkb(result, pg, pn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (instr->ExtractBit(4) == 1) { + mov_merging(pd, pg, result); + } else { + mov_zeroing(pd, pg, result); + } + + // Set flag if needed. + if (instr->ExtractBit(22) == 1) { + PredTest(kFormatVnB, pg, pd); + } +} + +void Simulator::VisitSVEPropagateBreakToNextPartition( + const Instruction* instr) { + SimPRegister& pdm = ReadPRegister(instr->GetPd()); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + + switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) { + case BRKNS_p_p_pp: + case BRKN_p_p_pp: + brkn(pdm, pg, pn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + // Set flag if needed. + if (instr->ExtractBit(22) == 1) { + // Note that this ignores `pg`. + PredTest(kFormatVnB, GetPTrue(), pdm); + } +} + +void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) { + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + + SimVRegister temp = Simulator::ExpandToSimVRegister(pn); + SimVRegister zero; + dup_immediate(kFormatVnB, zero, 0); + + switch (instr->Mask(SVEUnpackPredicateElementsMask)) { + case PUNPKHI_p_p: + zip2(kFormatVnB, temp, temp, zero); + break; + case PUNPKLO_p_p: + zip1(kFormatVnB, temp, temp, zero); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp); +} + +void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + SimPRegister& pm = ReadPRegister(instr->GetPm()); + + SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn); + SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm); + + switch (instr->Mask(SVEPermutePredicateElementsMask)) { + case TRN1_p_pp: + trn1(vform, temp0, temp0, temp1); + break; + case TRN2_p_pp: + trn2(vform, temp0, temp0, temp1); + break; + case UZP1_p_pp: + uzp1(vform, temp0, temp0, temp1); + break; + case UZP2_p_pp: + uzp2(vform, temp0, temp0, temp1); + break; + case ZIP1_p_pp: + zip1(vform, temp0, temp0, temp1); + break; + case ZIP2_p_pp: + zip2(vform, temp0, temp0, temp1); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0); +} + +void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) { + switch (instr->Mask(SVEReversePredicateElementsMask)) { + case REV_p_p: { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimVRegister temp = Simulator::ExpandToSimVRegister(pn); + rev(vform, temp, temp); + Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) { + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + // Second source register "Zm" is encoded where "Zn" would usually be. + SimVRegister& zm = ReadVRegister(instr->GetRn()); + + int index = instr->GetSVEExtractImmediate(); + int vl = GetVectorLengthInBytes(); + index = (index >= vl) ? 0 : index; + + switch (instr->Mask(SVEPermuteVectorExtractMask)) { + case EXT_z_zi_des: + ext(kFormatVnB, zdn, zdn, zm, index); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + switch (instr->Mask(SVEPermuteVectorInterleavingMask)) { + case TRN1_z_zz: + trn1(vform, zd, zn, zm); + break; + case TRN2_z_zz: + trn2(vform, zd, zn, zm); + break; + case UZP1_z_zz: + uzp1(vform, zd, zn, zm); + break; + case UZP2_z_zz: + uzp2(vform, zd, zn, zm); + break; + case ZIP1_z_zz: + zip1(vform, zd, zn, zm); + break; + case ZIP2_z_zz: + zip2(vform, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEConditionallyBroadcastElementToVector( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + int active_offset = -1; + switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) { + case CLASTA_z_p_zz: + active_offset = 1; + break; + case CLASTB_z_p_zz: + active_offset = 0; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (active_offset >= 0) { + std::pair value = clast(vform, pg, zm, active_offset); + if (value.first) { + dup_immediate(vform, zdn, value.second); + } else { + // Trigger a line of trace for the operation, even though it doesn't + // change the register value. + mov(vform, zdn, zdn); + } + } +} + +void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& vdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + int active_offset = -1; + switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) { + case CLASTA_v_p_z: + active_offset = 1; + break; + case CLASTB_v_p_z: + active_offset = 0; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (active_offset >= 0) { + LogicVRegister dst(vdn); + uint64_t src1_value = dst.Uint(vform, 0); + std::pair src2_value = clast(vform, pg, zm, active_offset); + dup_immediate(vform, vdn, 0); + dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value); + } +} + +void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + int active_offset = -1; + switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) { + case CLASTA_r_p_z: + active_offset = 1; + break; + case CLASTB_r_p_z: + active_offset = 0; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (active_offset >= 0) { + std::pair value = clast(vform, pg, zm, active_offset); + uint64_t masked_src = ReadXRegister(instr->GetRd()) & + GetUintMask(LaneSizeInBitsFromFormat(vform)); + WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src); + } +} + +void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& vdn = ReadVRegister(instr->GetRd()); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + int active_offset = -1; + switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) { + case LASTA_v_p_z: + active_offset = 1; + break; + case LASTB_v_p_z: + active_offset = 0; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (active_offset >= 0) { + LogicVRegister dst(vdn); + std::pair value = clast(vform, pg, zm, active_offset); + dup_immediate(vform, vdn, 0); + dst.SetUint(vform, 0, value.second); + } +} + +void Simulator::VisitSVEExtractElementToGeneralRegister( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zm = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + int active_offset = -1; + switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) { + case LASTA_r_p_z: + active_offset = 1; + break; + case LASTB_r_p_z: + active_offset = 0; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (active_offset >= 0) { + std::pair value = clast(vform, pg, zm, active_offset); + WriteXRegister(instr->GetRd(), value.second); + } +} + +void Simulator::VisitSVECompressActiveElements(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + switch (instr->Mask(SVECompressActiveElementsMask)) { + case COMPACT_z_p_z: + compact(vform, zd, pg, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated( + const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister z_result; + + switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) { + case CPY_z_p_r: + dup_immediate(vform, + z_result, + ReadXRegister(instr->GetRn(), Reg31IsStackPointer)); + mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16)); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + + SimVRegister result; + switch (instr->Mask(SVECopyIntImm_PredicatedMask)) { + case CPY_z_p_i: { + // Use unsigned arithmetic to avoid undefined behaviour during the shift. + uint64_t imm8 = instr->GetImmSVEIntWideSigned(); + dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8)); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (instr->ExtractBit(14) != 0) { + mov_merging(vform, zd, pg, result); + } else { + mov_zeroing(vform, zd, pg, result); + } +} + +void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + SimVRegister result; + + // In NEON, the chunk size in which elements are REVersed is in the + // instruction mnemonic, and the element size attached to the register. + // SVE reverses the semantics; the mapping to logic functions below is to + // account for this. + VectorFormat chunk_form = instr->GetSVEVectorFormat(); + VectorFormat element_form = kFormatUndefined; + + switch (instr->Mask(SVEReverseWithinElementsMask)) { + case RBIT_z_p_z: + rbit(chunk_form, result, zn); + break; + case REVB_z_z: + VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) || + (chunk_form == kFormatVnD)); + element_form = kFormatVnB; + break; + case REVH_z_z: + VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD)); + element_form = kFormatVnH; + break; + case REVW_z_z: + VIXL_ASSERT(chunk_form == kFormatVnD); + element_form = kFormatVnS; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) { + VIXL_ASSERT(element_form != kFormatUndefined); + switch (chunk_form) { + case kFormatVnH: + rev16(element_form, result, zn); + break; + case kFormatVnS: + rev32(element_form, result, zn); + break; + case kFormatVnD: + rev64(element_form, result, zn); + break; + default: + VIXL_UNIMPLEMENTED(); + } + } + + mov_merging(chunk_form, zd, pg, result); +} + +void Simulator::VisitSVEVectorSplice(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters); + SimPRegister& pg = ReadPRegister(instr->GetPgLow8()); + + switch (form_hash_) { + case "splice_z_p_zz_des"_h: + splice(vform, zd, pg, zd, zn); + break; + case "splice_z_p_zz_con"_h: + splice(vform, zd, pg, zn, zn2); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) { + case DUP_z_r: + dup_immediate(instr->GetSVEVectorFormat(), + zd, + ReadXRegister(instr->GetRn(), Reg31IsStackPointer)); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) { + case INSR_z_v: + insr(vform, zd, ReadDRegisterBits(instr->GetRn())); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + switch (instr->Mask(SVEInsertGeneralRegisterMask)) { + case INSR_z_r: + insr(vform, zd, ReadXRegister(instr->GetRn())); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + switch (instr->Mask(SVEBroadcastIndexElementMask)) { + case DUP_z_zi: { + std::pair index_and_lane_size = + instr->GetSVEPermuteIndexAndLaneSizeLog2(); + int index = index_and_lane_size.first; + int lane_size_in_bytes_log_2 = index_and_lane_size.second; + VectorFormat vform = + SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2); + if ((index < 0) || (index >= LaneCountFromFormat(vform))) { + // Out of bounds, set the destination register to zero. + dup_immediate(kFormatVnD, zd, 0); + } else { + dup_element(vform, zd, ReadVRegister(instr->GetRn()), index); + } + return; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + switch (instr->Mask(SVEReverseVectorElementsMask)) { + case REV_z_z: + rev(vform, zd, ReadVRegister(instr->GetRn())); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) { + SimVRegister& zd = ReadVRegister(instr->GetRd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + switch (instr->Mask(SVEUnpackVectorElementsMask)) { + case SUNPKHI_z_z: + unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend); + break; + case SUNPKLO_z_z: + unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend); + break; + case UUNPKHI_z_z: + unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend); + break; + case UUNPKLO_z_z: + unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVETableLookup(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + switch (form_hash_) { + case "tbl_z_zz_1"_h: + tbl(vform, zd, zn, zm); + break; + case "tbl_z_zz_2"_h: + tbl(vform, zd, zn, zn2, zm); + break; + case "tbx_z_zz"_h: + tbx(vform, zd, zn, zm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPredicateCount(const Instruction* instr) { + VectorFormat vform = instr->GetSVEVectorFormat(); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + + switch (instr->Mask(SVEPredicateCountMask)) { + case CNTP_r_p_p: { + WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn)); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPredicateLogical(const Instruction* instr) { + Instr op = instr->Mask(SVEPredicateLogicalMask); + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + SimPRegister& pm = ReadPRegister(instr->GetPm()); + SimPRegister result; + switch (op) { + case ANDS_p_p_pp_z: + case AND_p_p_pp_z: + case BICS_p_p_pp_z: + case BIC_p_p_pp_z: + case EORS_p_p_pp_z: + case EOR_p_p_pp_z: + case NANDS_p_p_pp_z: + case NAND_p_p_pp_z: + case NORS_p_p_pp_z: + case NOR_p_p_pp_z: + case ORNS_p_p_pp_z: + case ORN_p_p_pp_z: + case ORRS_p_p_pp_z: + case ORR_p_p_pp_z: + SVEPredicateLogicalHelper(static_cast(op), + result, + pn, + pm); + break; + case SEL_p_p_pp: + sel(pd, pg, pn, pm); + return; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + mov_zeroing(pd, pg, result); + if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) { + PredTest(kFormatVnB, pg, pd); + } +} + +void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) { + LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5)); + LogicPRegister pdn = ReadPRegister(instr->GetPd()); + switch (instr->Mask(SVEPredicateFirstActiveMask)) { + case PFIRST_p_p_p: + pfirst(pdn, pg, pdn); + // TODO: Is this broken when pg == pdn? + PredTest(kFormatVnB, pg, pdn); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) { + // This group only contains PTRUE{S}, and there are no unallocated encodings. + VIXL_STATIC_ASSERT( + SVEPredicateInitializeMask == + (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit)); + VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) || + (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s)); + + LogicPRegister pdn = ReadPRegister(instr->GetPd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + + ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint()); + if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn); +} + +void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) { + // This group only contains PNEXT, and there are no unallocated encodings. + VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask); + VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p); + + LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5)); + LogicPRegister pdn = ReadPRegister(instr->GetPd()); + VectorFormat vform = instr->GetSVEVectorFormat(); + + pnext(vform, pdn, pg, pdn); + // TODO: Is this broken when pg == pdn? + PredTest(vform, pg, pdn); +} + +void Simulator::VisitSVEPredicateReadFromFFR_Predicated( + const Instruction* instr) { + LogicPRegister pd(ReadPRegister(instr->GetPd())); + LogicPRegister pg(ReadPRegister(instr->GetPn())); + FlagsUpdate flags = LeaveFlags; + switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) { + case RDFFR_p_p_f: + // Do nothing. + break; + case RDFFRS_p_p_f: + flags = SetFlags; + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + LogicPRegister ffr(ReadFFR()); + mov_zeroing(pd, pg, ffr); + + if (flags == SetFlags) { + PredTest(kFormatVnB, pg, pd); + } +} + +void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated( + const Instruction* instr) { + LogicPRegister pd(ReadPRegister(instr->GetPd())); + LogicPRegister ffr(ReadFFR()); + switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) { + case RDFFR_p_f: + mov(pd, ffr); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPredicateTest(const Instruction* instr) { + switch (instr->Mask(SVEPredicateTestMask)) { + case PTEST_p_p: + PredTest(kFormatVnB, + ReadPRegister(instr->ExtractBits(13, 10)), + ReadPRegister(instr->GetPn())); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPredicateZero(const Instruction* instr) { + switch (instr->Mask(SVEPredicateZeroMask)) { + case PFALSE_p: + pfalse(ReadPRegister(instr->GetPd())); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEPropagateBreak(const Instruction* instr) { + SimPRegister& pd = ReadPRegister(instr->GetPd()); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimPRegister& pn = ReadPRegister(instr->GetPn()); + SimPRegister& pm = ReadPRegister(instr->GetPm()); + + bool set_flags = false; + switch (instr->Mask(SVEPropagateBreakMask)) { + case BRKPAS_p_p_pp: + set_flags = true; + VIXL_FALLTHROUGH(); + case BRKPA_p_p_pp: + brkpa(pd, pg, pn, pm); + break; + case BRKPBS_p_p_pp: + set_flags = true; + VIXL_FALLTHROUGH(); + case BRKPB_p_p_pp: + brkpb(pd, pg, pn, pm); + break; + default: + VIXL_UNIMPLEMENTED(); + break; + } + + if (set_flags) { + PredTest(kFormatVnB, pg, pd); + } +} + +void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) { + uint64_t length = 0; + switch (instr->Mask(SVEStackFrameAdjustmentMask)) { + case ADDPL_r_ri: + length = GetPredicateLengthInBytes(); + break; + case ADDVL_r_ri: + length = GetVectorLengthInBytes(); + break; + default: + VIXL_UNIMPLEMENTED(); + } + uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer); + WriteXRegister(instr->GetRd(), + base + (length * instr->GetImmSVEVLScale()), + LogRegWrites, + Reg31IsStackPointer); +} + +void Simulator::VisitSVEStackFrameSize(const Instruction* instr) { + int64_t scale = instr->GetImmSVEVLScale(); + + switch (instr->Mask(SVEStackFrameSizeMask)) { + case RDVL_r_i: + WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale); + break; + default: + VIXL_UNIMPLEMENTED(); + } +} + +void Simulator::VisitSVEVectorSelect(const Instruction* instr) { + // The only instruction in this group is `sel`, and there are no unused + // encodings. + VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz); + + VectorFormat vform = instr->GetSVEVectorFormat(); + SimVRegister& zd = ReadVRegister(instr->GetRd()); + SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10)); + SimVRegister& zn = ReadVRegister(instr->GetRn()); + SimVRegister& zm = ReadVRegister(instr->GetRm()); + + sel(vform, zd, pg, zn, zm); +} + +void Simulator::VisitSVEFFRInitialise(const Instruction* instr) { + switch (instr->Mask(SVEFFRInitialiseMask)) { + case SETFFR_f: { + LogicPRegister ffr(ReadFFR()); + ffr.SetAllBits(); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) { + switch (instr->Mask(SVEFFRWriteFromPredicateMask)) { + case WRFFR_f_p: { + SimPRegister pn(ReadPRegister(instr->GetPn())); + bool last_active = true; + for (unsigned i = 0; i < pn.GetSizeInBits(); i++) { + bool active = pn.GetBit(i); + if (active && !last_active) { + // `pn` is non-monotonic. This is UNPREDICTABLE. + VIXL_ABORT(); + } + last_active = active; + } + mov(ReadFFR(), pn); + break; + } + default: + VIXL_UNIMPLEMENTED(); + break; + } +} + +void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) { + bool is_signed; + switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) { + case LD1B_z_p_bi_u8: + case LD1B_z_p_bi_u16: + case LD1B_z_p_bi_u32: + case LD1B_z_p_bi_u64: + case LD1H_z_p_bi_u16: + case LD1H_z_p_bi_u32: + case LD1H_z_p_bi_u64: + case LD1W_z_p_bi_u32: + case LD1W_z_p_bi_u64: + case LD1D_z_p_bi_u64: + is_signed = false; + break; + case LD1SB_z_p_bi_s16: + case LD1SB_z_p_bi_s32: + case LD1SB_z_p_bi_s64: + case LD1SH_z_p_bi_s32: + case LD1SH_z_p_bi_s64: + case LD1SW_z_p_bi_s64: + is_signed = true; + break; + default: + // This encoding group is complete, so no other values should be possible. + VIXL_UNREACHABLE(); + is_signed = false; + break; + } + + int vl = GetVectorLengthInBytes(); + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed); + VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2); + int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2; + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = + (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredLoadHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + is_signed); +} + +void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar( + const Instruction* instr) { + bool is_signed; + switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) { + case LD1B_z_p_br_u8: + case LD1B_z_p_br_u16: + case LD1B_z_p_br_u32: + case LD1B_z_p_br_u64: + case LD1H_z_p_br_u16: + case LD1H_z_p_br_u32: + case LD1H_z_p_br_u64: + case LD1W_z_p_br_u32: + case LD1W_z_p_br_u64: + case LD1D_z_p_br_u64: + is_signed = false; + break; + case LD1SB_z_p_br_s16: + case LD1SB_z_p_br_s32: + case LD1SB_z_p_br_s64: + case LD1SH_z_p_br_s32: + case LD1SH_z_p_br_s64: + case LD1SW_z_p_br_s64: + is_signed = true; + break; + default: + // This encoding group is complete, so no other values should be possible. + VIXL_UNREACHABLE(); + is_signed = false; + break; + } + + int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed); + int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed); + VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2); + VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2); + uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t offset = ReadXRegister(instr->GetRm()); + offset <<= msize_in_bytes_log2; + LogicSVEAddressVector addr(base + offset); + addr.SetMsizeInBytesLog2(msize_in_bytes_log2); + SVEStructuredLoadHelper(vform, + ReadPRegister(instr->GetPgLow8()), + instr->GetRt(), + addr, + is_signed); +} + +void Simulator::DoUnreachable(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kUnreachableOpcode)); + + fprintf(stream_, + "Hit UNREACHABLE marker at pc=%p.\n", + reinterpret_cast(instr)); + abort(); +} + +void Simulator::Simulate_XdSP_XnSP_Xm(const Instruction* instr) { + VIXL_ASSERT(form_hash_ == Hash("irg_64i_dp_2src")); + uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t rm = ReadXRegister(instr->GetRm()); + uint64_t tag = GenerateRandomTag(rm & 0xffff); + uint64_t new_val = GetAddressWithAllocationTag(rn, tag); + WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer); +} + +void Simulator::SimulateMTEAddSubTag(const Instruction* instr) { + uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t rn_tag = GetAllocationTagFromAddress(rn); + uint64_t tag_offset = instr->ExtractBits(13, 10); + // TODO: implement GCR_EL1.Exclude to provide a tag exclusion list. + uint64_t new_tag = ChooseNonExcludedTag(rn_tag, tag_offset); + + uint64_t offset = instr->ExtractBits(21, 16) * kMTETagGranuleInBytes; + int carry = 0; + if (form_hash_ == Hash("subg_64_addsub_immtags")) { + offset = ~offset; + carry = 1; + } else { + VIXL_ASSERT(form_hash_ == Hash("addg_64_addsub_immtags")); + } + uint64_t new_val = + AddWithCarry(kXRegSize, /* set_flags = */ false, rn, offset, carry); + new_val = GetAddressWithAllocationTag(new_val, new_tag); + WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer); +} + +void Simulator::SimulateMTETagMaskInsert(const Instruction* instr) { + VIXL_ASSERT(form_hash_ == Hash("gmi_64g_dp_2src")); + uint64_t mask = ReadXRegister(instr->GetRm()); + uint64_t tag = GetAllocationTagFromAddress( + ReadXRegister(instr->GetRn(), Reg31IsStackPointer)); + uint64_t mask_bit = uint64_t{1} << tag; + WriteXRegister(instr->GetRd(), mask | mask_bit); +} + +void Simulator::SimulateMTESubPointer(const Instruction* instr) { + uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t rm = ReadXRegister(instr->GetRm(), Reg31IsStackPointer); + + VIXL_ASSERT((form_hash_ == Hash("subps_64s_dp_2src")) || + (form_hash_ == Hash("subp_64s_dp_2src"))); + bool set_flags = (form_hash_ == Hash("subps_64s_dp_2src")); + + rn = ExtractSignedBitfield64(55, 0, rn); + rm = ExtractSignedBitfield64(55, 0, rm); + uint64_t new_val = AddWithCarry(kXRegSize, set_flags, rn, ~rm, 1); + WriteXRegister(instr->GetRd(), new_val); +} + +void Simulator::SimulateMTEStoreTagPair(const Instruction* instr) { + uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer); + uint64_t rt = ReadXRegister(instr->GetRt()); + uint64_t rt2 = ReadXRegister(instr->GetRt2()); + int offset = instr->GetImmLSPair() * static_cast(kMTETagGranuleInBytes); + + AddrMode addr_mode = Offset; + switch (form_hash_) { + case Hash("stgp_64_ldstpair_off"): + // Default is the offset mode. + break; + case Hash("stgp_64_ldstpair_post"): + addr_mode = PostIndex; + break; + case Hash("stgp_64_ldstpair_pre"): + addr_mode = PreIndex; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode); + if (!IsAligned(address, kMTETagGranuleInBytes)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + + int tag = GetAllocationTagFromAddress(rn); + meta_data_.SetMTETag(address, tag); + + if (!MemWrite(address, rt)) return; + if (!MemWrite(address + kXRegSizeInBytes, rt2)) return; +} + +void Simulator::SimulateMTEStoreTag(const Instruction* instr) { + uint64_t rt = ReadXRegister(instr->GetRt(), Reg31IsStackPointer); + int offset = instr->GetImmLS() * static_cast(kMTETagGranuleInBytes); + + AddrMode addr_mode = Offset; + switch (form_hash_) { + case Hash("st2g_64soffset_ldsttags"): + case Hash("stg_64soffset_ldsttags"): + case Hash("stz2g_64soffset_ldsttags"): + case Hash("stzg_64soffset_ldsttags"): + // Default is the offset mode. + break; + case Hash("st2g_64spost_ldsttags"): + case Hash("stg_64spost_ldsttags"): + case Hash("stz2g_64spost_ldsttags"): + case Hash("stzg_64spost_ldsttags"): + addr_mode = PostIndex; + break; + case Hash("st2g_64spre_ldsttags"): + case Hash("stg_64spre_ldsttags"): + case Hash("stz2g_64spre_ldsttags"): + case Hash("stzg_64spre_ldsttags"): + addr_mode = PreIndex; + break; + default: + VIXL_UNIMPLEMENTED(); + } + + bool is_pair = false; + switch (form_hash_) { + case Hash("st2g_64soffset_ldsttags"): + case Hash("st2g_64spost_ldsttags"): + case Hash("st2g_64spre_ldsttags"): + case Hash("stz2g_64soffset_ldsttags"): + case Hash("stz2g_64spost_ldsttags"): + case Hash("stz2g_64spre_ldsttags"): + is_pair = true; + break; + default: + break; + } + + bool is_zeroing = false; + switch (form_hash_) { + case Hash("stz2g_64soffset_ldsttags"): + case Hash("stz2g_64spost_ldsttags"): + case Hash("stz2g_64spre_ldsttags"): + case Hash("stzg_64soffset_ldsttags"): + case Hash("stzg_64spost_ldsttags"): + case Hash("stzg_64spre_ldsttags"): + is_zeroing = true; + break; + default: + break; + } + + uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode); + + if (is_zeroing) { + if (!IsAligned(address, kMTETagGranuleInBytes)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + VIXL_STATIC_ASSERT(kMTETagGranuleInBytes >= sizeof(uint64_t)); + VIXL_STATIC_ASSERT(kMTETagGranuleInBytes % sizeof(uint64_t) == 0); + + size_t fill_size = kMTETagGranuleInBytes; + if (is_pair) { + fill_size += kMTETagGranuleInBytes; + } + + size_t fill_offset = 0; + while (fill_offset < fill_size) { + if (!MemWrite(address + fill_offset, 0)) return; + fill_offset += sizeof(uint64_t); + } + } + + int tag = GetAllocationTagFromAddress(rt); + meta_data_.SetMTETag(address, tag, instr); + if (is_pair) { + meta_data_.SetMTETag(address + kMTETagGranuleInBytes, tag, instr); + } +} + +void Simulator::SimulateMTELoadTag(const Instruction* instr) { + uint64_t rt = ReadXRegister(instr->GetRt()); + int offset = instr->GetImmLS() * static_cast(kMTETagGranuleInBytes); + + switch (form_hash_) { + case Hash("ldg_64loffset_ldsttags"): + break; + default: + VIXL_UNIMPLEMENTED(); + } + + uintptr_t address = AddressModeHelper(instr->GetRn(), offset, Offset); + address = AlignDown(address, kMTETagGranuleInBytes); + uint64_t tag = meta_data_.GetMTETag(address, instr); + WriteXRegister(instr->GetRt(), GetAddressWithAllocationTag(rt, tag)); +} + +void Simulator::SimulateCpyFP(const Instruction* instr) { + MOPSPHelper<"cpy"_h>(instr); + LogSystemRegister(NZCV); +} + +void Simulator::SimulateCpyP(const Instruction* instr) { + MOPSPHelper<"cpy"_h>(instr); + + int d = instr->GetRd(); + int n = instr->GetRn(); + int s = instr->GetRs(); + + // Determine copy direction. For cases in which direction is implementation + // defined, use forward. + bool is_backwards = false; + uint64_t xs = ReadXRegister(s); + uint64_t xd = ReadXRegister(d); + uint64_t xn = ReadXRegister(n); + + // Ignore the top byte of addresses for comparisons. We can use xn as is, + // as it should have zero in bits 63:55. + uint64_t xs_tbi = ExtractUnsignedBitfield64(55, 0, xs); + uint64_t xd_tbi = ExtractUnsignedBitfield64(55, 0, xd); + VIXL_ASSERT(ExtractUnsignedBitfield64(63, 55, xn) == 0); + if ((xs_tbi < xd_tbi) && ((xs_tbi + xn) > xd_tbi)) { + is_backwards = true; + WriteXRegister(s, xs + xn); + WriteXRegister(d, xd + xn); + } + + ReadNzcv().SetN(is_backwards ? 1 : 0); + LogSystemRegister(NZCV); +} + +void Simulator::SimulateCpyM(const Instruction* instr) { + VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>()); + VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "cpy"_h)); + + int d = instr->GetRd(); + int n = instr->GetRn(); + int s = instr->GetRs(); + + uint64_t xd = ReadXRegister(d); + uint64_t xn = ReadXRegister(n); + uint64_t xs = ReadXRegister(s); + bool is_backwards = ReadN(); + + int step = 1; + if (is_backwards) { + step = -1; + xs--; + xd--; + } + + while (xn--) { + VIXL_DEFINE_OR_RETURN(temp, MemRead(xs)); + if (!MemWrite(xd, temp)) return; + LogMemTransfer(xd, xs, temp); + xs += step; + xd += step; + } + + if (is_backwards) { + xs++; + xd++; + } + + WriteXRegister(d, xd); + WriteXRegister(n, 0); + WriteXRegister(s, xs); +} + +void Simulator::SimulateCpyE(const Instruction* instr) { + USE(instr); + VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>()); + VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "cpy"_h)); + // This implementation does nothing in the epilogue; all copying is completed + // in the "main" part. +} + +void Simulator::SimulateSetP(const Instruction* instr) { + MOPSPHelper<"set"_h>(instr); + LogSystemRegister(NZCV); +} + +void Simulator::SimulateSetM(const Instruction* instr) { + VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>()); + VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "set"_h)); + + uint64_t xd = ReadXRegister(instr->GetRd()); + uint64_t xn = ReadXRegister(instr->GetRn()); + uint64_t xs = ReadXRegister(instr->GetRs()); + + while (xn--) { + LogWrite(instr->GetRs(), GetPrintRegPartial(kPrintRegLaneSizeB), xd); + if (!MemWrite(xd++, static_cast(xs))) return; + } + WriteXRegister(instr->GetRd(), xd); + WriteXRegister(instr->GetRn(), 0); +} + +void Simulator::SimulateSetE(const Instruction* instr) { + USE(instr); + VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>()); + VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "set"_h)); + // This implementation does nothing in the epilogue; all setting is completed + // in the "main" part. +} + +void Simulator::SimulateSetGP(const Instruction* instr) { + MOPSPHelper<"setg"_h>(instr); + + uint64_t xd = ReadXRegister(instr->GetRd()); + uint64_t xn = ReadXRegister(instr->GetRn()); + + if ((xn > 0) && !IsAligned(xd, kMTETagGranuleInBytes)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + + if (!IsAligned(xn, kMTETagGranuleInBytes)) { + VIXL_ALIGNMENT_EXCEPTION(); + } + + LogSystemRegister(NZCV); +} + +void Simulator::SimulateSetGM(const Instruction* instr) { + uint64_t xd = ReadXRegister(instr->GetRd()); + uint64_t xn = ReadXRegister(instr->GetRn()); + + int tag = GetAllocationTagFromAddress(xd); + while (xn) { + meta_data_.SetMTETag(xd, tag); + xd += 16; + xn -= 16; + } + SimulateSetM(instr); +} + +void Simulator::DoTrace(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kTraceOpcode)); + + // Read the arguments encoded inline in the instruction stream. + uint32_t parameters; + uint32_t command; + + VIXL_STATIC_ASSERT(sizeof(*instr) == 1); + memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters)); + memcpy(&command, instr + kTraceCommandOffset, sizeof(command)); + + switch (command) { + case TRACE_ENABLE: + SetTraceParameters(GetTraceParameters() | parameters); + break; + case TRACE_DISABLE: + SetTraceParameters(GetTraceParameters() & ~parameters); + break; + default: + VIXL_UNREACHABLE(); + } + + WritePc(instr->GetInstructionAtOffset(kTraceLength)); +} + + +void Simulator::DoLog(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kLogOpcode)); + + // Read the arguments encoded inline in the instruction stream. + uint32_t parameters; + + VIXL_STATIC_ASSERT(sizeof(*instr) == 1); + memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters)); + + // We don't support a one-shot LOG_DISASM. + VIXL_ASSERT((parameters & LOG_DISASM) == 0); + // Print the requested information. + if (parameters & LOG_SYSREGS) PrintSystemRegisters(); + if (parameters & LOG_REGS) PrintRegisters(); + if (parameters & LOG_VREGS) PrintVRegisters(); + + WritePc(instr->GetInstructionAtOffset(kLogLength)); +} + + +void Simulator::DoPrintf(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kPrintfOpcode)); + + // Read the arguments encoded inline in the instruction stream. + uint32_t arg_count; + uint32_t arg_pattern_list; + VIXL_STATIC_ASSERT(sizeof(*instr) == 1); + memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count)); + memcpy(&arg_pattern_list, + instr + kPrintfArgPatternListOffset, + sizeof(arg_pattern_list)); + + VIXL_ASSERT(arg_count <= kPrintfMaxArgCount); + VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0); + + // We need to call the host printf function with a set of arguments defined by + // arg_pattern_list. Because we don't know the types and sizes of the + // arguments, this is very difficult to do in a robust and portable way. To + // work around the problem, we pick apart the format string, and print one + // format placeholder at a time. + + // Allocate space for the format string. We take a copy, so we can modify it. + // Leave enough space for one extra character per expected argument (plus the + // '\0' termination). + const char* format_base = ReadRegister(0); + VIXL_ASSERT(format_base != NULL); + size_t length = strlen(format_base) + 1; + char* const format = new char[length + arg_count]; + + // A list of chunks, each with exactly one format placeholder. + const char* chunks[kPrintfMaxArgCount]; + + // Copy the format string and search for format placeholders. + uint32_t placeholder_count = 0; + char* format_scratch = format; + for (size_t i = 0; i < length; i++) { + if (format_base[i] != '%') { + *format_scratch++ = format_base[i]; + } else { + if (format_base[i + 1] == '%') { + // Ignore explicit "%%" sequences. + *format_scratch++ = format_base[i]; + i++; + // Chunks after the first are passed as format strings to printf, so we + // need to escape '%' characters in those chunks. + if (placeholder_count > 0) *format_scratch++ = format_base[i]; + } else { + VIXL_CHECK(placeholder_count < arg_count); + // Insert '\0' before placeholders, and store their locations. + *format_scratch++ = '\0'; + chunks[placeholder_count++] = format_scratch; + *format_scratch++ = format_base[i]; + } + } + } + VIXL_CHECK(placeholder_count == arg_count); + + // Finally, call printf with each chunk, passing the appropriate register + // argument. Normally, printf returns the number of bytes transmitted, so we + // can emulate a single printf call by adding the result from each chunk. If + // any call returns a negative (error) value, though, just return that value. + + printf("%s", clr_printf); + + // Because '\0' is inserted before each placeholder, the first string in + // 'format' contains no format placeholders and should be printed literally. + int result = printf("%s", format); + int pcs_r = 1; // Start at x1. x0 holds the format string. + int pcs_f = 0; // Start at d0. + if (result >= 0) { + for (uint32_t i = 0; i < placeholder_count; i++) { + int part_result = -1; + + uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits); + arg_pattern &= (1 << kPrintfArgPatternBits) - 1; + switch (arg_pattern) { + case kPrintfArgW: + part_result = printf(chunks[i], ReadWRegister(pcs_r++)); + break; + case kPrintfArgX: + part_result = printf(chunks[i], ReadXRegister(pcs_r++)); + break; + case kPrintfArgD: + part_result = printf(chunks[i], ReadDRegister(pcs_f++)); + break; + default: + VIXL_UNREACHABLE(); + } + + if (part_result < 0) { + // Handle error values. + result = part_result; + break; + } + + result += part_result; + } + } + + printf("%s", clr_normal); + + // Printf returns its result in x0 (just like the C library's printf). + WriteXRegister(0, result); + + // The printf parameters are inlined in the code, so skip them. + WritePc(instr->GetInstructionAtOffset(kPrintfLength)); + + // Set LR as if we'd just called a native printf function. + WriteLr(ReadPc()); + + delete[] format; +} + + +#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT +void Simulator::DoRuntimeCall(const Instruction* instr) { + VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t)); + // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function + // to call are passed inlined in the assembly. + VIXL_DEFINE_OR_RETURN(call_wrapper_address, + MemRead(instr + kRuntimeCallWrapperOffset)); + VIXL_DEFINE_OR_RETURN(function_address, + MemRead(instr + kRuntimeCallFunctionOffset)); + VIXL_DEFINE_OR_RETURN(call_type, + MemRead(instr + kRuntimeCallTypeOffset)); + auto runtime_call_wrapper = + reinterpret_cast(call_wrapper_address); + + if (static_cast(call_type) == kCallRuntime) { + const Instruction* addr = instr->GetInstructionAtOffset(kRuntimeCallLength); + WriteLr(addr); + GCSPush(reinterpret_cast(addr)); + } + runtime_call_wrapper(this, function_address); + // Read the return address from `lr` and write it into `pc`. + uint64_t addr = ReadRegister(kLinkRegCode); + if (IsGCSCheckEnabled()) { + uint64_t expected_lr = GCSPeek(); + char msg[128]; + if (expected_lr != 0) { + if ((expected_lr & 0x3) != 0) { + snprintf(msg, + sizeof(msg), + "GCS contains misaligned return address: 0x%016" PRIx64 "\n", + expected_lr); + ReportGCSFailure(msg); + } else if ((addr != 0) && (addr != expected_lr)) { + snprintf(msg, + sizeof(msg), + "GCS mismatch: lr = 0x%016" PRIx64 ", gcs = 0x%016" PRIx64 + "\n", + addr, + expected_lr); + ReportGCSFailure(msg); + } + GCSPop(); + } + } + WritePc(reinterpret_cast(addr)); +} +#else +void Simulator::DoRuntimeCall(const Instruction* instr) { + USE(instr); + VIXL_UNREACHABLE(); +} +#endif + + +void Simulator::DoConfigureCPUFeatures(const Instruction* instr) { + VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT); + + typedef ConfigureCPUFeaturesElementType ElementType; + VIXL_ASSERT(CPUFeatures::kNumberOfFeatures < + std::numeric_limits::max()); + + // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding. + + size_t element_size = sizeof(ElementType); + size_t offset = kConfigureCPUFeaturesListOffset; + + // Read the kNone-terminated list of features. + CPUFeatures parameters; + while (true) { + VIXL_DEFINE_OR_RETURN(feature, MemRead(instr + offset)); + offset += element_size; + if (feature == static_cast(CPUFeatures::kNone)) break; + parameters.Combine(static_cast(feature)); + } + + switch (instr->GetImmException()) { + case kSetCPUFeaturesOpcode: + SetCPUFeatures(parameters); + break; + case kEnableCPUFeaturesOpcode: + GetCPUFeatures()->Combine(parameters); + break; + case kDisableCPUFeaturesOpcode: + GetCPUFeatures()->Remove(parameters); + break; + default: + VIXL_UNREACHABLE(); + break; + } + + WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize))); +} + + +void Simulator::DoSaveCPUFeatures(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kSaveCPUFeaturesOpcode)); + USE(instr); + + saved_cpu_features_.push_back(*GetCPUFeatures()); +} + + +void Simulator::DoRestoreCPUFeatures(const Instruction* instr) { + VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) && + (instr->GetImmException() == kRestoreCPUFeaturesOpcode)); + USE(instr); + + SetCPUFeatures(saved_cpu_features_.back()); + saved_cpu_features_.pop_back(); +} + +#ifdef VIXL_HAS_SIMULATED_MMAP +void* Simulator::Mmap( + void* address, size_t length, int prot, int flags, int fd, off_t offset) { + // The underlying system `mmap` in the simulated environment doesn't recognize + // PROT_BTI and PROT_MTE. Although the kernel probably just ignores the bits + // it doesn't know, mask those protections out before calling is safer. + int intenal_prot = prot; + prot &= ~(PROT_BTI | PROT_MTE); + + uint64_t address2 = reinterpret_cast( + mmap(address, length, prot, flags, fd, offset)); + + if (intenal_prot & PROT_MTE) { + // The returning address of `mmap` isn't tagged. + int tag = static_cast(GenerateRandomTag()); + SetGranuleTag(address2, tag, length); + address2 = GetAddressWithAllocationTag(address2, tag); + } + + return reinterpret_cast(address2); +} + + +int Simulator::Munmap(void* address, size_t length, int prot) { + if (prot & PROT_MTE) { + // Untag the address since `munmap` doesn't recognize the memory tagging + // managed by the Simulator. + address = AddressUntag(address); + CleanGranuleTag(reinterpret_cast(address), length); + } + + return munmap(address, length); +} +#endif // VIXL_HAS_SIMULATED_MMAP + +} // namespace aarch64 +} // namespace vixl + +#endif // VIXL_INCLUDE_SIMULATOR_AARCH64 diff --git a/3rdparty/vixl/src/utils-vixl.cc b/3rdparty/vixl/src/utils-vixl.cc index 639a4b1957..356837d043 100644 --- a/3rdparty/vixl/src/utils-vixl.cc +++ b/3rdparty/vixl/src/utils-vixl.cc @@ -34,14 +34,19 @@ namespace vixl { const double kFP64DefaultNaN = RawbitsToDouble(UINT64_C(0x7ff8000000000000)); const float kFP32DefaultNaN = RawbitsToFloat(0x7fc00000); const Float16 kFP16DefaultNaN = RawbitsToFloat16(0x7e00); +const BFloat16 kBFP16DefaultNaN = RawbitsToBFloat16(0x7fc0); // Floating-point zero values. const Float16 kFP16PositiveZero = RawbitsToFloat16(0x0); const Float16 kFP16NegativeZero = RawbitsToFloat16(0x8000); +const BFloat16 kBFP16PositiveZero = RawbitsToBFloat16(0x0); +const BFloat16 kBFP16NegativeZero = RawbitsToBFloat16(0x8000); // Floating-point infinity values. const Float16 kFP16PositiveInfinity = RawbitsToFloat16(0x7c00); const Float16 kFP16NegativeInfinity = RawbitsToFloat16(0xfc00); +const BFloat16 kBFP16PositiveInfinity = RawbitsToBFloat16(0x7f80); +const BFloat16 kBFP16NegativeInfinity = RawbitsToBFloat16(0xff80); const float kFP32PositiveInfinity = RawbitsToFloat(0x7f800000); const float kFP32NegativeInfinity = RawbitsToFloat(0xff800000); const double kFP64PositiveInfinity = @@ -57,6 +62,14 @@ bool IsZero(Float16 value) { uint16_t Float16ToRawbits(Float16 value) { return value.rawbits_; } +bool IsZero(BFloat16 value) { + uint16_t bits = BFloat16ToRawbits(value); + return (bits == BFloat16ToRawbits(kBFP16PositiveZero) || + bits == BFloat16ToRawbits(kBFP16NegativeZero)); +} + +uint16_t BFloat16ToRawbits(BFloat16 value) { return value.rawbits_; } + uint32_t FloatToRawbits(float value) { uint32_t bits = 0; memcpy(&bits, &value, 4); @@ -78,6 +91,13 @@ Float16 RawbitsToFloat16(uint16_t bits) { } +BFloat16 RawbitsToBFloat16(uint16_t bits) { + BFloat16 f; + f.rawbits_ = bits; + return f; +} + + float RawbitsToFloat(uint32_t bits) { float value = 0.0; memcpy(&value, &bits, 4); @@ -552,4 +572,76 @@ Float16 FPToFloat16(double value, return kFP16PositiveZero; } +BFloat16 FPToBFloat16(float value, + FPRounding round_mode, + UseDefaultNaN DN, + bool* exception) { + // Only the FPTieEven rounding mode is implemented. + VIXL_ASSERT(round_mode == FPTieEven); + USE(round_mode); + + uint32_t raw = FloatToRawbits(value); + int32_t sign = raw >> 31; + int32_t exponent = + static_cast(ExtractUnsignedBitfield32(30, 23, raw)) - 127; + uint32_t mantissa = ExtractUnsignedBitfield32(22, 0, raw); + + switch (std::fpclassify(value)) { + case FP_NAN: { + if (IsSignallingNaN(value)) { + if (exception != NULL) { + *exception = true; + } + } + if (DN == kUseDefaultNaN) return kBFP16DefaultNaN; + + // Convert NaNs as the processor would: + // - The sign is propagated. + // - The payload (mantissa) is transferred as much as possible, except + // that the top bit is forced to '1', making the result a quiet NaN. + uint16_t result = (sign == 0) ? BFloat16ToRawbits(kBFP16PositiveInfinity) + : BFloat16ToRawbits(kBFP16NegativeInfinity); + result |= mantissa >> (kFloatMantissaBits - kBFloat16MantissaBits); + result |= (1 << 6); // Force a quiet NaN; + return RawbitsToBFloat16(result); + } + + case FP_ZERO: + return (sign == 0) ? kBFP16PositiveZero : kBFP16NegativeZero; + + case FP_INFINITE: + return (sign == 0) ? kBFP16PositiveInfinity : kBFP16NegativeInfinity; + + case FP_NORMAL: + // Add the implicit '1' bit to the mantissa. + mantissa += (1 << 23); + break; + + case FP_SUBNORMAL: + // Reduce exponent to account for MSB of mantissa. + int32_t leading_mantissa_bits = + CountLeadingZeros(mantissa) - (32 - kFloatMantissaBits); + exponent -= leading_mantissa_bits; + break; + } + + // Convert float-to-half as the processor would, assuming that FPCR.FZ + // (flush-to-zero) is not set. + return FPRoundToBFloat16(sign, exponent, mantissa, round_mode); +} + +BFloat16 FPToBFloat16(double value, + FPRounding round_mode, + UseDefaultNaN DN, + bool* exception) { + USE(value); + USE(round_mode); + USE(DN); + USE(exception); + // TODO: Implement this for correct conversion of doubles to BFloat (without + // implicit NaN silencing.) + VIXL_UNIMPLEMENTED(); + return kBFP16PositiveZero; +} + } // namespace vixl diff --git a/3rdparty/vixl/vixl.vcxproj b/3rdparty/vixl/vixl.vcxproj index 90ca615829..1dbb7047ef 100644 --- a/3rdparty/vixl/vixl.vcxproj +++ b/3rdparty/vixl/vixl.vcxproj @@ -76,6 +76,7 @@ + @@ -84,6 +85,7 @@ + diff --git a/3rdparty/vixl/vixl.vcxproj.filters b/3rdparty/vixl/vixl.vcxproj.filters index 1f01277166..78b3152419 100644 --- a/3rdparty/vixl/vixl.vcxproj.filters +++ b/3rdparty/vixl/vixl.vcxproj.filters @@ -65,6 +65,9 @@ aarch64 + + aarch64 + aarch64 @@ -89,6 +92,9 @@ aarch64 + + aarch64 + aarch64 diff --git a/3rdparty/xbyak/xbyak/xbyak.h b/3rdparty/xbyak/xbyak/xbyak.h index 623281bd46..127fd41588 100644 --- a/3rdparty/xbyak/xbyak/xbyak.h +++ b/3rdparty/xbyak/xbyak/xbyak.h @@ -15,7 +15,7 @@ #include // for debug print #include -#include +#include #include #include #ifndef NDEBUG @@ -116,10 +116,12 @@ #undef XBYAK_USE_MEMFD #endif -#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__)) - #define XBYAK64_WIN -#elif defined(__x86_64__) - #define XBYAK64_GCC +#if !defined(XBYAK64_WIN) && !defined(XBYAK64_GCC) + #if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__)) + #define XBYAK64_WIN + #elif defined(__x86_64__) + #define XBYAK64_GCC + #endif #endif #if !defined(XBYAK64) && !defined(XBYAK32) #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN) @@ -174,7 +176,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x7352 /* 0xABCD = A.BC(.D) */ + VERSION = 0x7370 /* 0xABCD = A.BC(.D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -1074,7 +1076,7 @@ public: } } friend RegExp operator+(const RegExp& a, const RegExp& b); - friend RegExp operator+(const RegExp& e, size_t disp); + friend RegExp operator+(const RegExp& e, unsigned long long disp); friend RegExp operator-(const RegExp& e, size_t disp); private: /* @@ -1128,15 +1130,19 @@ inline RegExp operator*(int scale, const Reg& r) // backward compatibility for eax+&x (pointer address) inline RegExp operator+(const RegExp& a, const void* b) { return a + RegExp(b); } -// overload for integer literals (e.g. eax+0) to avoid ambiguity with the void* overload -inline RegExp operator+(const RegExp& e, int disp) { return e + size_t(disp); } - -inline RegExp operator+(const RegExp& e, size_t disp) +// since what size_t is typedef'd to depends on the implementation, use unsigned long long (assume u64) for the implementation. +inline RegExp operator+(const RegExp& e, unsigned long long disp) { RegExp ret = e; - ret.disp_ += disp; + ret.disp_ += static_cast(disp); return ret; } +// overload for integer literals (e.g. eax+0) to avoid ambiguity with the void* overload +inline RegExp operator+(const RegExp& e, int disp) { return e + static_cast(disp); } +inline RegExp operator+(const RegExp& e, long disp) { return e + static_cast(disp); } +inline RegExp operator+(const RegExp& e, long long disp) { return e + static_cast(disp); } +inline RegExp operator+(const RegExp& e, unsigned int disp) { return e + static_cast(disp); } +inline RegExp operator+(const RegExp& e, unsigned long disp) { return e + static_cast(disp); } inline RegExp operator-(const RegExp& e, size_t disp) { @@ -1172,7 +1178,7 @@ class CodeArray { return disp; } }; - typedef std::list AddrInfoList; + typedef std::vector AddrInfoList; AddrInfoList addrInfoList_; const Type type_; #ifdef XBYAK_USE_MMAP_ALLOCATOR @@ -1319,7 +1325,7 @@ public: */ void rewrite(size_t offset, uint64_t disp, size_t size) { - assert(offset < maxSize_); + if (offset >= maxSize_ || size > maxSize_ - offset) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG) if (size != 1 && size != 2 && size != 4 && size != 8) XBYAK_THROW(ERR_BAD_PARAMETER) uint8_t *const data = top_ + offset; for (size_t i = 0; i < size; i++) { @@ -1363,7 +1369,7 @@ public: DWORD oldProtect; return VirtualProtect(const_cast(addr), size, mode, &oldProtect) != 0; #elif defined(__GNUC__) - size_t pageSize = sysconf(_SC_PAGESIZE); + size_t pageSize = inner::getPageSize(); size_t iaddr = reinterpret_cast(addr); size_t roundAddr = iaddr & ~(pageSize - static_cast(1)); return mprotect(reinterpret_cast(roundAddr), size + (iaddr - roundAddr), mode) == 0; @@ -1548,7 +1554,8 @@ class LabelManager { SlabelDefList defList; SlabelUndefList undefList; }; - typedef std::list StateList; + // SlabelState is cheap to move, so std::vector is preferred over std::list. + typedef std::vector StateList; // for Label class struct ClabelVal { ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {} diff --git a/3rdparty/xbyak/xbyak/xbyak_mnemonic.h b/3rdparty/xbyak/xbyak/xbyak_mnemonic.h index 961d88f85f..94288e7de8 100644 --- a/3rdparty/xbyak/xbyak/xbyak_mnemonic.h +++ b/3rdparty/xbyak/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "7.35.2"; } +const char *getVersionString() const { return "7.37"; } void aadd(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38, 0x0FC, T_APX); } void aand(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38|T_66, 0x0FC, T_APX|T_66); } void adc(const Operand& op, uint32_t imm) { opOI(op, imm, 0x10, 2); } @@ -853,7 +853,6 @@ void prefetcht0(const Address& addr) { opMR(addr, Reg32(1), T_0F, 0x18); } void prefetcht1(const Address& addr) { opMR(addr, Reg32(2), T_0F, 0x18); } void prefetcht2(const Address& addr) { opMR(addr, Reg32(3), T_0F, 0x18); } void prefetchw(const Address& addr) { opMR(addr, Reg32(1), T_0F, 0x0D); } -void prefetchwt1(const Address& addr) { opMR(addr, Reg32(2), T_0F, 0x0D); } void psadbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF6); } void pshufb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x00, T_0F38, T_66); } void pshufd(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, T_0F, T_66, imm8); } @@ -2036,10 +2035,6 @@ void kxorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2 void kxord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x47); } void kxorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x47); } void kxorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x47); } -void v4fmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_W0 | T_YMM | T_MUST_EVEX | T_N16, 0x9A); } -void v4fmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_W0 | T_MUST_EVEX | T_N16, 0x9B); } -void v4fnmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_W0 | T_YMM | T_MUST_EVEX | T_N16, 0xAA); } -void v4fnmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_W0 | T_MUST_EVEX | T_N16, 0xAB); } void vaddbf16(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x58); } void vaddph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_W0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x58); } void vaddsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_W0 | T_MUST_EVEX | T_ER_X | T_N2, 0x58); } @@ -2199,10 +2194,10 @@ void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4|T void vcomxsd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8|T_F2|T_0F|T_EW1|T_SAE_X|T_MUST_EVEX, 0x2F); } void vcomxsh(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2|T_F3|T_MAP5|T_W0|T_SAE_X|T_MUST_EVEX, 0x2F); } void vcomxss(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4|T_F3|T_0F|T_W0|T_SAE_X|T_MUST_EVEX, 0x2F); } -void vcvt2ph2bf8(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N1|T_F2|T_0F38|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x74); } -void vcvt2ph2bf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N1|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x74); } -void vcvt2ph2hf8(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N1|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x18); } -void vcvt2ph2hf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N1|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x1B); } +void vcvt2ph2bf8(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16|T_N_VL|T_F2|T_0F38|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x74); } +void vcvt2ph2bf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16|T_N_VL|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x74); } +void vcvt2ph2hf8(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16|T_N_VL|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x18); } +void vcvt2ph2hf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16|T_N_VL|T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x1B); } void vcvt2ps2phx(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66|T_0F38|T_W0|T_YMM|T_ER_Z|T_MUST_EVEX|T_B32, 0x67); } void vcvtbf162ibs(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x69); } void vcvtbf162iubs(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2|T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x6B); } @@ -2211,7 +2206,7 @@ void vcvtbiasph2bf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt6(x void vcvtbiasph2hf8(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt6(x1, x2, op, T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x18); } void vcvtbiasph2hf8s(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt6(x1, x2, op, T_MAP5|T_W0|T_YMM|T_MUST_EVEX|T_B16, 0x1B); } void vcvtdq2ph(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16|T_N_VL|T_MAP5|T_W0|T_YMM|T_ER_Z|T_MUST_EVEX|T_B32, 0x5B); } -void vcvthf82ph(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_MUST_EVEX | T_F2 | T_MAP5 | T_W0 | T_YMM | T_N1, 0x1E); } +void vcvthf82ph(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_MUST_EVEX|T_F2|T_MAP5|T_W0|T_YMM|T_N8|T_N_VL, 0x1E); } void vcvtne2ps2bf16(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2|T_0F38|T_W0|T_YMM|T_SAE_Z|T_MUST_EVEX|T_B32, 0x72); } void vcvtpd2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16|T_N_VL|T_66|T_MAP5|T_EW1|T_ER_Z|T_MUST_EVEX|T_B64, 0x5A); } void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66|T_0F|T_EW1|T_YMM|T_ER_Z|T_MUST_EVEX|T_B64, 0x7B); } @@ -2437,8 +2432,6 @@ void vmulph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) void vmulsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_W0 | T_MUST_EVEX | T_ER_X | T_N2, 0x59); } void vp2intersectd(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_W0 | T_B32, 0x68); } void vp2intersectq(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW1 | T_B64, 0x68); } -void vp4dpwssd(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_W0 | T_YMM | T_MUST_EVEX | T_N16, 0x52); } -void vp4dpwssds(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_W0 | T_YMM | T_MUST_EVEX | T_N16, 0x53); } void vpabsq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_B64 | T_YMM, 0x1F); } void vpandd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66|T_0F|T_W0|T_YMM|T_MUST_EVEX|T_B32, 0xDB); } void vpandnd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66|T_0F|T_W0|T_YMM|T_MUST_EVEX|T_B32, 0xDF); } diff --git a/3rdparty/xbyak/xbyak/xbyak_util.h b/3rdparty/xbyak/xbyak/xbyak_util.h index cb6365c951..a75d3f937b 100644 --- a/3rdparty/xbyak/xbyak/xbyak_util.h +++ b/3rdparty/xbyak/xbyak/xbyak_util.h @@ -101,6 +101,8 @@ #endif #ifdef _WIN32 #include +#else +#include #endif namespace Xbyak { namespace util { class CpuTopology; @@ -526,16 +528,16 @@ public: XBYAK_DEFINE_TYPE(36, tAVX512DQ); XBYAK_DEFINE_TYPE(37, tAVX512_IFMA); XBYAK_DEFINE_TYPE(37, tAVX512IFMA);// = tAVX512_IFMA; - XBYAK_DEFINE_TYPE(38, tAVX512PF); - XBYAK_DEFINE_TYPE(39, tAVX512ER); +// XBYAK_DEFINE_TYPE(38, tAVX512PF); // Xeon Phi only +// XBYAK_DEFINE_TYPE(39, tAVX512ER); XBYAK_DEFINE_TYPE(40, tAVX512CD); XBYAK_DEFINE_TYPE(41, tAVX512BW); XBYAK_DEFINE_TYPE(42, tAVX512VL); XBYAK_DEFINE_TYPE(43, tAVX512_VBMI); XBYAK_DEFINE_TYPE(43, tAVX512VBMI); // = tAVX512_VBMI; // changed by Intel's manual - XBYAK_DEFINE_TYPE(44, tAVX512_4VNNIW); - XBYAK_DEFINE_TYPE(45, tAVX512_4FMAPS); - XBYAK_DEFINE_TYPE(46, tPREFETCHWT1); +// XBYAK_DEFINE_TYPE(44, tAVX512_4VNNIW); +// XBYAK_DEFINE_TYPE(45, tAVX512_4FMAPS); +// XBYAK_DEFINE_TYPE(46, tPREFETCHWT1); XBYAK_DEFINE_TYPE(47, tPREFETCHW); XBYAK_DEFINE_TYPE(48, tSHA); XBYAK_DEFINE_TYPE(49, tMPX); @@ -587,6 +589,7 @@ public: XBYAK_DEFINE_TYPE(95, tAMX_FP8); XBYAK_DEFINE_TYPE(96, tMOVRS); XBYAK_DEFINE_TYPE(97, tHYBRID); + XBYAK_DEFINE_TYPE(98, tAMX_COMPLEX); #undef XBYAK_SPLIT_ID #undef XBYAK_DEFINE_TYPE @@ -679,8 +682,6 @@ public: if (type_ & tAVX512F) { if (ebx & (1U << 17)) type_ |= tAVX512DQ; if (ebx & (1U << 21)) type_ |= tAVX512_IFMA; - if (ebx & (1U << 26)) type_ |= tAVX512PF; - if (ebx & (1U << 27)) type_ |= tAVX512ER; if (ebx & (1U << 28)) type_ |= tAVX512CD; if (ebx & (1U << 30)) type_ |= tAVX512BW; if (ebx & (1U << 31)) type_ |= tAVX512VL; @@ -689,8 +690,6 @@ public: if (ecx & (1U << 11)) type_ |= tAVX512_VNNI; if (ecx & (1U << 12)) type_ |= tAVX512_BITALG; if (ecx & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ; - if (edx & (1U << 2)) type_ |= tAVX512_4VNNIW; - if (edx & (1U << 3)) type_ |= tAVX512_4FMAPS; if (edx & (1U << 8)) type_ |= tAVX512_VP2INTERSECT; if ((type_ & tAVX512BW) && (edx & (1U << 23))) type_ |= tAVX512_FP16; } @@ -713,7 +712,6 @@ public: if (ebx & (1U << 23)) type_ |= tCLFLUSHOPT; if (ebx & (1U << 24)) type_ |= tCLWB; if (ebx & (1U << 29)) type_ |= tSHA; - if (ecx & (1U << 0)) type_ |= tPREFETCHWT1; if (ecx & (1U << 5)) type_ |= tWAITPKG; if (ecx & (1U << 8)) type_ |= tGFNI; if (ecx & (1U << 9)) type_ |= tVAES; @@ -745,6 +743,7 @@ public: if (eax & (1U << 31)) type_ |= tMOVRS; if (edx & (1U << 4)) type_ |= tAVX_VNNI_INT8; if (edx & (1U << 5)) type_ |= tAVX_NE_CONVERT; + if (edx & (1U << 8)) type_ |= tAMX_COMPLEX; if (edx & (1U << 10)) type_ |= tAVX_VNNI_INT16; if (edx & (1U << 14)) type_ |= tPREFETCHITI; if (edx & (1U << 19)) type_ |= tAVX10; @@ -1296,11 +1295,57 @@ inline uint32_t popcnt(uint64_t mask) #endif } +// fall back to CPUID leaf 0x1A +inline CoreType getCoreType() +{ + uint32_t data[4] = {}; + Cpu::getCpuidEx(0x1A, 0, data); + const uint32_t coreTypeField = (data[0] >> 24) & 0xFF; + if (coreTypeField == 0x40) return Performance; // P-core + if (coreTypeField == 0x20) return Efficient; // E-core + return Standard; +} + #ifdef _WIN32 typedef std::vector U32Vec; + +#if (defined(NTDDI_VERSION) && NTDDI_VERSION >= 0x06010000) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0601) + #define XBYAK_WINSDK_HAS_RELATIONSHIP_GROUP_AFFINITY 1 +#else + #define XBYAK_WINSDK_HAS_RELATIONSHIP_GROUP_AFFINITY 0 +#endif + +#if (defined(NTDDI_VERSION) && NTDDI_VERSION >= 0x0A000000) || (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0A00) + #define XBYAK_WINSDK_HAS_EFFICIENCY_CLASS 1 +#else + #define XBYAK_WINSDK_HAS_EFFICIENCY_CLASS 0 +#endif + +// GroupMasks[] / GroupCount on CACHE_RELATIONSHIP added in Win10 20H1 (SDK 10.0.19041, NTDDI_WIN10_VB) +// NOTE: _WIN32_WINNT has no sub-version granularity for Win10, so only +// NTDDI_VERSION can distinguish 20H1 (0x0A00000C) from earlier Win10 builds. +// If NTDDI_VERSION is not set, this macro will be 0 (safe/conservative fallback). +#if defined(NTDDI_VERSION) && NTDDI_VERSION >= 0x0A00000C + #define XBYAK_WINSDK_HAS_CACHE_RELATIONSHIP_GROUPMASKS 1 +#else + #define XBYAK_WINSDK_HAS_CACHE_RELATIONSHIP_GROUPMASKS 0 +#endif + +#if XBYAK_WINSDK_HAS_RELATIONSHIP_GROUP_AFFINITY typedef SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ProcInfo; +inline CoreType getCoreTypeForAffinity(const GROUP_AFFINITY& affinity) +{ + GROUP_AFFINITY previousMask = {}; + if (!SetThreadGroupAffinity(GetCurrentThread(), &affinity, &previousMask)) { + return Standard; + } + CoreType type = impl::getCoreType(); + SetThreadGroupAffinity(GetCurrentThread(), &previousMask, NULL); + return type; +} + // return total logical cpus if sucessful, 0 if failed inline uint32_t getGroupAcc(U32Vec& v) { @@ -1346,10 +1391,12 @@ static inline uint32_t getCores(std::vector& cpus, bool isHybrid, co cpu.coreId = coreIdx++; if (!isHybrid) { cpu.coreType = Standard; - } else if (core.EfficiencyClass > 0) { - cpu.coreType = Performance; } else { - cpu.coreType = Efficient; +#if XBYAK_WINSDK_HAS_EFFICIENCY_CLASS + cpu.coreType = core.EfficiencyClass > 0 ? Performance : Efficient; +#else + cpu.coreType = getCoreTypeForAffinity(core.GroupMask[0]); +#endif } const GROUP_AFFINITY* masks = core.GroupMask; @@ -1374,13 +1421,19 @@ static inline uint32_t getCores(std::vector& cpus, bool isHybrid, co inline bool convertMask(CpuMask& mask, const U32Vec& groupAcc, const CACHE_RELATIONSHIP& cache) { - const GROUP_AFFINITY* masks = cache.GroupMasks; - - for (WORD i = 0; i < cache.GroupCount; i++) { - const WORD group = masks[i].Group; - const KAFFINITY m = masks[i].Mask; - const uint32_t base = groupAcc[group]; - +#if XBYAK_WINSDK_HAS_CACHE_RELATIONSHIP_GROUPMASKS + const WORD count = cache.GroupCount; +#else + const WORD count = 1; +#endif + for (WORD i = 0; i < count; i++) { +#if XBYAK_WINSDK_HAS_CACHE_RELATIONSHIP_GROUPMASKS + const GROUP_AFFINITY& cg = cache.GroupMasks[i]; +#else + const GROUP_AFFINITY& cg = cache.GroupMask; +#endif + const KAFFINITY m = cg.Mask; + const uint32_t base = groupAcc[cg.Group]; for (uint32_t b = 0; b < sizeof(KAFFINITY) * 8; b++) { if (m & (KAFFINITY(1) << b)) { if (!mask.append(base + b)) return false; @@ -1441,7 +1494,17 @@ inline bool initCpuTopology(CpuTopology& cpuTopo) } return true; } - +#else +inline bool initCpuTopology(CpuTopology& cpuTopo) +{ + (void)cpuTopo; + return false; +} +#endif +// unset WinSDK version macros to avoid Macro pollution +#undef XBYAK_WINSDK_HAS_RELATIONSHIP_GROUP_AFFINITY +#undef XBYAK_WINSDK_HAS_EFFICIENCY_CLASS +#undef XBYAK_WINSDK_HAS_CACHE_RELATIONSHIP_GROUPMASKS #elif defined(__linux__) // Linux struct WrapFILE { @@ -1471,6 +1534,15 @@ inline bool parseCpuList(CpuMask& mask, const char* path) { return setStr(mask, buf); } +inline CoreType setAffinityAndGetCoreType(uint32_t cpu) +{ + cpu_set_t cpuMask; + CPU_ZERO(&cpuMask); + CPU_SET(cpu, &cpuMask); + if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuMask)) return Standard; + return impl::getCoreType(); +} + inline bool initCpuTopology(CpuTopology& cpuTopo) { const uint32_t logicalCpuNum = sysconf(_SC_NPROCESSORS_ONLN); @@ -1564,9 +1636,10 @@ inline bool initCpuTopology(CpuTopology& cpuTopo) // Assign core types for hybrid architectures const bool isHybrid = cpuTopo.isHybrid(); if (isHybrid) { - // For hybrid systems, read P-core and E-core lists from sysfs + // For hybrid systems, try toread P-core and E-core lists from sysfs first CpuMask pCoreMask; - if (parseCpuList(pCoreMask, "/sys/devices/cpu_core/cpus")) { + const bool hasPCoreSysfs = parseCpuList(pCoreMask, "/sys/devices/cpu_core/cpus"); + if (hasPCoreSysfs) { // Set Performance core types for (CpuMask::const_iterator it = pCoreMask.begin(); it != pCoreMask.end(); ++it) { uint32_t cpuIdx = *it; @@ -1576,7 +1649,8 @@ inline bool initCpuTopology(CpuTopology& cpuTopo) } } CpuMask eCoreMask; - if (parseCpuList(eCoreMask, "/sys/devices/cpu_atom/cpus")) { + const bool hasECoreSysfs = parseCpuList(eCoreMask, "/sys/devices/cpu_atom/cpus"); + if (hasECoreSysfs) { // Set Efficient core types for (CpuMask::const_iterator it = eCoreMask.begin(); it != eCoreMask.end(); ++it) { uint32_t cpuIdx = *it; @@ -1585,6 +1659,17 @@ inline bool initCpuTopology(CpuTopology& cpuTopo) } } } + // Fallback: if either sysfs paths are unavailable, detect both core type per-CPU + if (!hasPCoreSysfs || !hasECoreSysfs) { + cpu_set_t originalMask; + CPU_ZERO(&originalMask); + if (sched_getaffinity(0, sizeof(cpu_set_t), &originalMask) == 0) { + for (uint32_t cpu = 0; cpu < logicalCpuNum; cpu++) { + cpuTopo.logicalCpus_[cpu].coreType = impl::setAffinityAndGetCoreType(cpu); + } + sched_setaffinity(0, sizeof(cpu_set_t), &originalMask); + } + } } // Read coherency line size @@ -1645,8 +1730,6 @@ private: }; #ifdef XBYAK64 -const int UseRCX = 1 << 6; -const int UseRDX = 1 << 7; class Pack { static const size_t maxTblNum = 15; @@ -1745,28 +1828,35 @@ public: } }; +// start from a bit position larger than the number of GPRs +const int UseRBP = 1 << 5; +const int UseRCX = 1 << 6; +const int UseRDX = 1 << 7; +const int UseRSI = 1 << 8; +const int UseRDI = 1 << 9; +const int UseRBPAsFramePointer = UseRBP | (1 << 10); + class StackFrame { #ifdef XBYAK64_WIN static const int noSaveNum = 6; - static const int rcxPos = 0; - static const int rdxPos = 1; #else static const int noSaveNum = 8; - static const int rcxPos = 3; - static const int rdxPos = 2; #endif + static const int maxPnum = 4; static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax + static const int calleeSaveNum = maxRegNum - noSaveNum; + static const int UseMASK = UseRCX|UseRDX|UseRSI|UseRDI|UseRBP; Xbyak::CodeGenerator *code_; - Xbyak::Reg64 pTbl_[4]; + Xbyak::Reg64 pTbl_[maxPnum]; Xbyak::Reg64 tTbl_[maxRegNum]; Pack p_; Pack t_; int pNum_; int tNum_; + int useRegs_; int saveNum_; + int saveRegs_[calleeSaveNum]; int P_; - bool useRcx_; - bool useRdx_; bool makeEpilog_; StackFrame(const StackFrame&); void operator=(const StackFrame&); @@ -1776,45 +1866,69 @@ public: /* make stack frame @param sf [in] this - @param pNum [in] num of function parameter(0 <= pNum <= 4) - @param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14 + @param pNum [in] number of function parameters(0 <= pNum <= 4) + @param tNum [in] number of temporary registers(0 <= tNum, can be OR-ed with Use{RCX,RDX,RSI,RDI,RBP}, e.g., 3|UseRCX) @param stackSizeByte [in] local stack size @param makeEpilog [in] automatically call close() if true + pNum + tNum + #Use must be <= 14 + you can use rax - gp0, ..., gp(pNum - 1) - gt0, ..., gt(tNum-1) - rcx if tNum & UseRCX - rdx if tNum & UseRDX - rsp[0..stackSizeByte - 1] + p[0], ..., p[pNum-1] as function parameters + t[0], ..., t[tNum-1] as temporary registers + {rcx,rdx,rsi,rdi,rbp} are explicitly available by specifying Use{RCX,RDX,RSI,RDI,RBP} in tNum + rsp[0..stackSizeByte-1] if stackSizeByte > 0 */ StackFrame(Xbyak::CodeGenerator *code, int pNum, int tNum = 0, int stackSizeByte = 0, bool makeEpilog = true) : code_(code) , pNum_(pNum) - , tNum_(tNum & ~(UseRCX | UseRDX)) + , tNum_(tNum & ~(UseMASK|UseRBPAsFramePointer)) + , useRegs_(tNum & UseMASK) // drop UseRBPAsFramePointer bit , saveNum_(0) , P_(0) - , useRcx_((tNum & UseRCX) != 0) - , useRdx_((tNum & UseRDX) != 0) , makeEpilog_(makeEpilog) , p(p_) , t(t_) { - using namespace Xbyak; if (pNum < 0 || pNum > 4) XBYAK_THROW(ERR_BAD_PNUM) - const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0); - if (tNum_ < 0 || allRegNum > maxRegNum) XBYAK_THROW(ERR_BAD_TNUM) - const Reg64& _rsp = code->rsp; - saveNum_ = local::max_(0, allRegNum - noSaveNum); - const int *tbl = getOrderTbl() + noSaveNum; - for (int i = 0; i < saveNum_; i++) { - code->push(Reg64(tbl[i])); + if (tNum < 0) XBYAK_THROW(ERR_BAD_TNUM) + const int *const fullTbl = getRegEntryTbl(); + const int *const calleeTbl = fullTbl + noSaveNum; + int callerUseNum = 0; + int calleeUseNum = 0; + for (int i = 0; i < maxRegNum; i++) { + if (useRegs_ & useFlagOf(fullTbl[i])) { + if (i < noSaveNum) { + callerUseNum++; + } else { + calleeUseNum++; + } + } + } + const int useNum = callerUseNum + calleeUseNum; + if (pNum + tNum_ + useNum > maxRegNum) XBYAK_THROW(ERR_BAD_TNUM) + const int baseSaveNum = local::max_(0, pNum + tNum_ + useNum - noSaveNum); + bool pushedRbp = false; + if (useRegs_ & UseRBP) { + code->push(rbp); + saveRegs_[saveNum_++] = Operand::RBP; + pushedRbp = true; + if ((tNum & UseRBPAsFramePointer) == UseRBPAsFramePointer) code->mov(rbp, rsp); + } + for (int i = 0; i < calleeSaveNum; i++) { + int r = calleeTbl[i]; + if (i < baseSaveNum || isUseReg(r)) { + if (pushedRbp && r == Operand::RBP) continue; + saveRegs_[saveNum_++] = r; + code->push(Reg64(r)); + } } P_ = (stackSizeByte + 7) / 8; - if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment + // (rsp % 16) == 8, then increment P_ for 16 byte alignment + if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; P_ *= 8; - if (P_ > 0) code->sub(_rsp, P_); + if (P_ > 0) code->sub(rsp, P_); int pos = 0; for (int i = 0; i < pNum; i++) { pTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); @@ -1822,8 +1936,13 @@ public: for (int i = 0; i < tNum_; i++) { tTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); } - if (useRcx_ && rcxPos < pNum) code_->mov(code_->r10, code_->rcx); - if (useRdx_ && rdxPos < pNum) code_->mov(code_->r11, code_->rdx); + // replace reserved reg with backup reg if needed + for (size_t i = 0; i < maxPnum; i++) { + const RegSlot& rp = getRegSlotTbl()[i]; + if (isUseReg(rp.target) && rp.pos < pNum && rp.alt >= 0) { + code->mov(Xbyak::Reg64(rp.alt), Xbyak::Reg64(rp.target)); + } + } p_.init(pTbl_, pNum); t_.init(tTbl_, tNum_); } @@ -1833,14 +1952,10 @@ public: */ void close(bool callRet = true) { - using namespace Xbyak; - const Reg64& _rsp = code_->rsp; - const int *tbl = getOrderTbl() + noSaveNum; - if (P_ > 0) code_->add(_rsp, P_); - for (int i = 0; i < saveNum_; i++) { - code_->pop(Reg64(tbl[saveNum_ - 1 - i])); + if (P_ > 0) code_->add(code_->rsp, P_); + for (int i = saveNum_ - 1; i >= 0; i--) { + code_->pop(Reg64(saveRegs_[i])); } - if (callRet) code_->ret(); } ~StackFrame() @@ -1849,10 +1964,48 @@ public: close(); } private: - const int *getOrderTbl() const + static int useFlagOf(int r) { - using namespace Xbyak; - static const int tbl[] = { + switch (r) { + case Operand::RCX: return UseRCX; + case Operand::RDX: return UseRDX; + case Operand::RSI: return UseRSI; + case Operand::RDI: return UseRDI; + case Operand::RBP: return UseRBP; + default: return 0; + } + } + bool isUseReg(int r) const { return (useRegs_ & useFlagOf(r)) != 0; } + // Register allocation for the first 4 function parameters + struct RegSlot { + int target; + int pos; // position of target in getRegEntryTbl() + int alt; // alternative if target is used for parameter. -1 means no alternative. + }; + const RegSlot *getRegSlotTbl() const + { + // Win: p[] = rcx(r10), rdx(r11), r8, r9: + // Linux: p[] = rdi(r8), rsi(r9), rdx(r11), rcx(r10) + // reg(alt) means a reserved reg if Use is used. + + static const RegSlot tbl[maxPnum] = { +#ifdef XBYAK64_WIN + { Operand::RCX, 0, Operand::R10 }, + { Operand::RDX, 1, Operand::R11 }, + { Operand::RDI, 6, -1 }, + { Operand::RSI, 7, -1 }, +#else + { Operand::RCX, 3, Operand::R10 }, + { Operand::RDX, 2, Operand::R11 }, + { Operand::RDI, 0, Operand::R8 }, + { Operand::RSI, 1, Operand::R9 }, +#endif + }; + return tbl; + } + const int *getRegEntryTbl() const + { + static const int tbl[maxRegNum] = { #ifdef XBYAK64_WIN Operand::RCX, Operand::RDX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, Operand::RDI, Operand::RSI, #else @@ -1862,21 +2015,28 @@ private: }; return &tbl[0]; } + // get an available register index from tbl, skipping reserved registers int getRegIdx(int& pos) const { - assert(pos < maxRegNum); - using namespace Xbyak; - const int *tbl = getOrderTbl(); - int r = tbl[pos++]; - if (useRcx_) { - if (r == Operand::RCX) { return Operand::R10; } - if (r == Operand::R10) { r = tbl[pos++]; } + const int *tbl = getRegEntryTbl(); + const RegSlot *slotTbl = getRegSlotTbl(); + for (;;) { + NEXT:; + assert(pos < maxRegNum); + int r = tbl[pos++]; + // if r is a Use*** target with alt, return alt as backup + // otherwise skip Use*** targets, their alts, and UseRBP's rbp + for (size_t i = 0; i < maxPnum; i++) { + const RegSlot& slot = slotTbl[i]; + if (!isUseReg(slot.target)) continue; + if (r == slot.alt) goto NEXT; + if (r == slot.target) { + if (slot.alt >= 0) return slot.alt; + goto NEXT; + } + } + if (!isUseReg(r)) return r; } - if (useRdx_) { - if (r == Operand::RDX) { return Operand::R11; } - if (r == Operand::R11) { return tbl[pos++]; } - } - return r; } }; #endif